最近公司的產品系統要重構,但是時間又比較緊迫,所以底層的結構如mongo mq的連接操作就直接用之前的jar包了,目前系統採用的maven多module模塊模式,最可恥的是webframework是用的play,而且大家也覺得替換spring在短時間內不好實現。所以只好去把paly服務作爲module集成到maven中了,這塊任務交到我這裏那就做吧,相關資料少之又少,通過git源碼及聯繫原作者,終於用maven play plugin的方式將play集成到maven中去了。下一步我的開發任務便是業務指標的梳理,整體上包括三部分:取數據的dateOperation層、algorithm層及指標計算層:即指標計算層調用其它兩層從而計算出指標。
dataOperation層: 1)簡單的mongo的crud操作,寫成工具類的形式;2)策略模式實現不同的取數及計算規則,返回指標計算想要的中間值。
algor層:僅僅的指標計算的算法,其實就是公式了。沒有多餘的取數及邏輯
index計算層:在指標計算過程中,用不同的策略計算中間值,然後調用相關算法來計算指標。
以上三層均定義接口及抽象類,java的多態還是蠻有用的。
然後最近在梳理業務,因爲有些指標計算不僅是簡單的入參然後輸出一個指標。譬如:
基金公司的某組合id 一段時間範圍內所有的持倉數據
1)根據持倉計算個券的指標
2)將所有的持倉根據type(股票、期貨、債券等等)分類,然後計算每一層的指標(sum(權重*個券) )。
3)股票層還要根據行業分類標準分成不同的行業層,每一層計算指標(sum(權重*個券))
呵呵,然後用了二天半時間,不斷地推翻重建,終於形成了一套初步的方式。這裏分享下,源碼如下:
clientParam.setCollection("bond_position");
Set<String> keySet = new HashSet<>();
keySet.add("combination_id");
keySet.add("date");
keySet.add("type");
keySet.add("code");
keySet.add("name");
keySet.add("value");
keySet.add("hq_close_price");
clientParam.setKey(keySet);
List<Map<String, Object>> totalBondList = (List<Map<String, Object>>) context.handle(params, clientParam);
//預處理 dimension的industryNames 及 map<code, level1_name>
clientParam.clearQueryParameters();
clientParam.setCollection("stock_category");
clientParam.setParam("industry_name_cd", "SW");
params.setParam("keyName", "ticker");
params.setParam("valName", "level1_name");
// map<code, level1_name>
Map<String, String> code_industry = (Map<String, String>) context.handle(params, clientParam);
//dimension的industryNames
clientParam.setGroup("$level1_name");
Stragtegy stragtegy2 = strategy.get("AggregateDataHandleStra");
context.setStrategy(stragtegy2);
List<String> industrayList = (List<String>) context.handle(params, clientParam);
//第一步 根據入參date及type及dimension將結構搭好
//date結構裏放入type結構
DateModel dateModel = new DateModel();
for(int type : new ArrayList<Integer>()) {
TypeModel typemodel = new TypeModel(type, "typeName");
dateModel.setTypeModel(type, typemodel);
}
//type爲股票的放入行業結構
TypeModel typeModel = dateModel.getTypeMap().get(1);
for(String industryName : industrayList) {
IndustryModel industryModel = new IndustryModel(industryName);
typeModel.setIndustryModel(industryName, industryModel);
}
//組合層次放入日期結構,此時用到了之前構建好的dateModel結構。
CombIdModel combIdModel = new CombIdModel(119);
for(Date date :new ArrayList<Date>()) {
combIdModel.setDateModel(date, dateModel);
}
//第二步 將範圍內個券轉換成singleBond對象,並將個體對象放到已搭建好的結構combIdModel合適位置
for(Map<String, Object> single1 : totalBondList) {
SingleBondModel single = new SingleBondModel();
//type date用來分類
int type = Integer.parseInt(single1.get("type").toString());
Date date = DateUtil.stringToDateGL(single1.get("date").toString());
String code = single1.get("code").toString();
//基本信息直接copy
single.setType(type);
single.setCode(code);
single.setDate(date);
//需要計算的指標計算完畢再set進對象,指標計算走之前的設計邏輯
Double initWeight = 0.001;
single.setInitWeight(initWeight);
single.setIdx(123.0);
//開始往combIdModel結構中放入 個券放入過程中在相應的層級累加initweight
if(1== type) {
combIdModel.getDateModel(date).addInitWeight(initWeight).getTypeModel(type).addInitWeight(initWeight).getIndustryModel(code_industry.get(code)).addInitWeight(initWeight).addSingle(single);
} else {
combIdModel.getDateModel(date).addInitWeight(initWeight).getTypeModel(type).addInitWeight(initWeight).addSingle(single);
}
}
//第三步 開始計算各維度的idx
combIdModel.calIdx();
一頭霧水對吧,其實思想層次是這樣:
先根據date type industry 把存放數據的結構建好,就好比你要把一羣乞丐放進收容所,你得先把收容所根據性別、年齡等建好男女宿舍、廁所等。
ok,存放數據的結構建好了,下一步就是把數據庫取出來的數據封裝成SingleBondModel對象並放入合適的位置,這裏在循環遍歷每一條數據的時候做了兩件事:
1、計算個券的指標idx,計算其權重initWeight。連同重要數據一併放入對象中
2、放到它本來應該在的位置,那就根據該單個對象的date、type、industry依次查找直至合適它的位置,在尋找過程中,將包括它的相應層級的initWeight加之
//開始往combIdModel結構中放入 個券放入過程中在相應的層級累加initweight
if(1== type) {
combIdModel.getDateModel(date).addInitWeight(initWeight).getTypeModel(type).addInitWeight(initWeight).getIndustryModel(code_industry.get(code)).addInitWeight(initWeight).addSingle(single);
} else {
combIdModel.getDateModel(date).addInitWeight(initWeight).getTypeModel(type).addInitWeight(initWeight).addSingle(single);
}
最後計算每一層的指標,這裏看似只調用了
//第三步 開始計算各維度的idx
combIdModel.calIdx();
但內部實現原理是這樣的:
首先combIdModel不同的層級包含了對應的對象,當調用combIdModel.calIdx()時,首先是計算每一日期的指標,每一日期的指標計算方法中會觸發下一級別層次的指標計算,直至找到最底層的SingleBondModel並計算之。
CombIdModel:
//觸發該組合下每一個DateModel的指標計算
@Override
public void calIdx() {
for(Date date : dateMap.keySet())
dateMap.get(date).calIdx();
}
DateModel:
//計算該DateModel的指標,由CombIdModel層觸發
@Override
public void calIdx() {
Double initSum = 0.0D;
for(int type : typeMap.keySet()) {
TypeModel typeModel = typeMap.get(type);
initSum += typeModel.calAndGetIdx() * typeModel.getInitWeight();
}
idx = initSum / initWeight;
TypeModel:
//在DateModel層調用calAndGetIdx()觸發
@Override
public void calIdx() {
if(null!=industryMap)
calIndustryMap();
else
calSingleList();
}
public void calIndustryMap() {
Double initSum = 0.0D;
for(String industryName : industryMap.keySet()) {
IndustryModel industryModel = industryMap.get(industryName);
initSum += industryModel.calAndGetIdx() * industryModel.getInitWeight();
}
idx = initSum / initWeight;
}
public void calSingleList() {
Double initSum = 0.0D;
for(SingleBondModel single : singleList) {
initSum += single.getIdx() * single.getInitWeight();
}
idx = initSum / initWeight;
}
IndustryModel:
//在TypeModel層調用calAndIdx方法觸發
@Override
public void calIdx() {
Double initSum = 0.0D;
for(SingleBondModel single : singleList) {
initSum += single.getIdx() * single.getInitWeight();
}
idx = initSum / initWeight;
}
這些model均實現了抽象類
/**
* model抽象層
* @author fujian
*
*/
public abstract class AbstrateModel implements Model {
Double idx;
@Override
public Double calAndGetIdx() {
calIdx(); //當前層級下觸發計算指標動作
return idx; //返回指標
}
public abstract void calIdx();
}
ok,好久不更博,總結mark下
然後被老闆嫌棄 棄用了…………….