2015-01-19 14:40:04
金魔方平台是由飛狐交易師原創團隊集多年研發經驗,依靠和訊財經網強大資源,吸取國際專家思路而推出的十年巨作。目前新出的這個2.0版,這一版在數據存儲方面作很大的改進,同等條件的滬深數據,飛狐和大交易師的存儲空間要2.4G多,而現在的金魔方只要350M的存儲空間,同一個指標選股飛狐大交易師要幾十秒鍾才有結果,金魔方只要幾秒鍾就有結果,並且沒有數據接收的困擾。金魔方軟件是一款具有划時代意義的量化投資平台軟件。它強大易用的策略編寫平台不但能編寫公式指標,更能輕松自如地編寫涉及資金管理、倉位控制的交易策略,充分表達您的投資思路和交易模型;它能在無限接近真實市場的模擬環境中全面細致地測評,從而幫助您研發、驗證、挑選最可能在將來的真實市場中穩健盈利的交易策略;它的模擬交易系統能讓你在私密環境中模擬測評你的策略;它的自動交易模塊能讓交易策略自動執行,從而助您克服人性弱點、突破生理極限,系統執行您的投資思想; 最后,它能使您非常便捷地任意組合不同策略,讓它們互相配合、抵消風險,實現長期穩健盈利。它在量化投資的所有環節給予您強大幫助,使量化投資變得簡單易行。從而使您能輕松運用量化投資,克服人性弱點、理性決策、健康投資。
目前大部分只知道如何使用金魔方,但是作為一名IT界的成員,我們更關心的是如何使用金魔方提供的金語言以及其提供的各種其它語言的接口來操作其金融數據,其提供的接口是開放的,數據是免費的,無須注冊。那么下面我們將一起來看看其相關的數據結構以及接口情況。
以下是金魔方的主頁面:
從上面的界面我們可以看到,中間是K線,左邊是公式編輯器,它的公式是采用自帶的金語言進行編寫的,我們先來介紹一下它自帶的金語言:
金語言參考手冊
一. 指標。
用金語言所編寫的程序稱之為“指標”。
二. 金語言指標的類型
金語言能夠生成五類指標。分別是:
1) 技術指標
2) 條件選股指標
3) 五彩K線指標
4) 自定義函數
5) 智能策略
技術指標:對證券數據進行計算、統計后得出的數據集合。通常需要顯示在軟件圖表上。
條件選股:是一類特別的技術指標,其特征是只允許輸出一個變量,而且這個變量必須是布爾值。
五彩K線指標:是一類特別的技術指標,它的用途很簡單,就是用於控制K線的顏色。所以這類指標也只輸出一個變量。這個變量存放的是K線的顏色。
自定義函數:用戶把一些常用的計算提煉出來,以方便以后反復使用。
智能策略:能夠直接作出交易動作的指標。
三. 金語言基礎元素
3.1 數據是怎樣計算的
序列
序列是很特別的一類數據。它跟數組很相像:可以通過下標訪問。
序列跟數組的區別:
數組在聲明時已經定義好元素數量,之后不會改變,而序列在聲明時並不指明元素數量。它的數量由K線數量決定,隨着行情進行,K線不斷增加,序列也相應的自動增加,並且是一一對應。
序列的下標:金語言中,序列下標0代表最近的一根K線所對應的序列數據;下標1代表前一根K線所對應的數據。
單值
單值是除序列之外的所有數據類型。單值可以是數字,也可以是字符串,甚至可以是定長數組。
內置序列
金語言內置了常用的行情序列數據。包括:開、高、低、收、量、額、日期、時間、持倉等。
計算模式
金語言有兩種計算模式。逐行計算和逐根計算。
逐行計算模式下,每次計算都對整個序列從頭到尾重新計算其值。
逐根計算模式下,每次計算時只計算序列最新一根的值----第一次載入圖表時除外,此時會從頭到尾對每一根K線進行逐根計算。
其中,智能策略和用戶自定義函數只能運行在逐根模式下。
3.2 變量的聲明
變量通過input(輸入參數)、variable進行聲明。
3.3 表達式
變量通過運算組成表達式。
3.4 輸出
所謂輸出,是指標運行時顯示數據,輸出數據。
金語言有多種輸出方式。
1. 通過“:”操作符或Plot函數輸出。
2. 通過畫線函數輸出。
3. 通過Explain、Print、Comment、聲音函數、Email等函數輸出。
3.5 控制語句
控制語句控制程序的執行。包括分支、循環等。
金語言有以下控制語言:
if、switch(case)、for、while、repeat
3.6 指標引用
技術指標能夠通過refindi函數引用另一個指標的輸出。
refindi只工作在逐行模式下。
3.7 數據引用
默認提供的高低收量額等數據對應於當前圖表上的品種和周期。如果要使用非當前圖表上的品種、周期的數據,可以通過refData函數取得。
3.8 自定義函數
自定義函數能夠很方便的擴展金語言,既比使用DLL這樣的手段簡單,運行效率又比引用指標的方式高。
自定義函數只能工作在逐根模式下。
自定義函數通常這樣使用:
1, 計算后返回一個值
2, 計算並填充引用參數。引用參數是自定義函數特殊的輸入參數,能夠在函數中計算,並把值帶出函數。
自定義函數所聲明的variable變量的值會保留,並能夠在下一次計算時使用。
四. 金語言與金魔方
金語言在金魔方中編寫、編譯;
指標能顯示在金魔方圖表上或用於選股、預警。
智能策略指標編寫之后,可以在金魔方中測評;
最后,智能策略可以通過金魔方實盤運行,並做出交易動作。
五. 金語言的擴展(用戶DLL的接入)
金語言允許用戶通過DLL增強金語言的能力。
金語言的DLL接口非常強大,相比之下,一般股軟都預先限定DLL的輸入參數,金語言則同時支持限定輸入參數的方式,也支持用戶描述的方式。
也就是說,用戶只需在金語言中撰寫函數描述,就能自由使用任意DLL函數包括,例如Windows Api中的函數。前提是這些函數用到的數據類型在金語言的支持之列------畢竟,金語言並未支持結構、指針等數據類型。
在介紹完金語言之后,我們正式進入金魔方平台的開發環節,首先我們點擊程式交易工具欄進入功式編輯器,如圖2所示:
公式編輯器中,開發人員可以直接使用它提供的金語言進行邏輯的編寫,也可以采用dll外掛的方式來編寫,上面圖2 我就是采用dll的外掛形式來進行程序編寫,dll外掛是指采用c或c++等高級語言編寫函數,最后編譯成dll的形式,然后用金語言調用,圖2的公式中,FOXFUNC是指dll的命名,TRADE_FIRST是指dll中編寫的函數名稱,var1是指函數的返回值,這個返回值可以是一個數或是一串數字。drawline是指根據返回值的序列來連接各個k線的點,其中返回的序列下標是和每一條k線的編號相對應的。
上在描述了具體的dll調用過程,下面來看看,如何調用金魔方的API接口以及金魔方的基本數據結構。
/* /////////////////////////////////////////////////////////////////////////// 飛狐交易師“C語言接口”擴展程序調用接口規范V3.0 1.本規范適用於飛狐交易師V3.x公式系統. 2.擴展函數用於實現系統函數不能實現的特殊算法. 3.擴展函數用windows 32位動態連接庫實現,建議使用Microsoft Visual C++編程. 4.調用時在公式編輯器中寫"動態庫名稱@函數名稱"(參數表)即可,例如下面函數可以寫為"FOXFUNC@MYMACLOSE"(5) 5.動態連接庫名稱和函數名稱可以自己定義. 6.使用時必須將動態庫拷貝到飛狐交易師安裝目錄下的FmlDLL子目錄下使用. */
1 //分析周期 2 //////////////////////////////////////////////////// 3 enum DATA_TYPE 4 { 5 TICK_DATA=2, //分筆成交 6 MIN1_DATA, //1分鍾線 7 MIN5_DATA, //5分鍾線 8 MIN15_DATA, //15分鍾線 9 MIN30_DATA, //30分鍾線 10 MIN60_DATA, //60分鍾線 11 DAY_DATA, //日線 12 WEEK_DATA, //周線 13 MONTH_DATA, //月線 14 YEAR_DATA, //年線 15 MULTIDAY_DATA, //多日線 16 MULTIMIN_DATA, //多分鍾線 17 MULTISEC_DATA //多秒線 18 }; 19 20 //////////////////////////////////////////////////// 21 //基本數據 22 //////////////////////////////////////////////////// 23 24 typedef struct tagSTKDATA 25 { 26 int m_time; //時間,UCT 27 //time_t m_time; 28 float m_fOpen; //開盤 29 float m_fHigh; //最高 30 float m_fLow; //最低 31 float m_fClose; //收盤 32 float m_fVolume; //成交量(手) 33 float m_fAmount; //成交額(元)/持倉(未平倉合約,僅期貨有效) 34 WORD m_wAdvance; //上漲家數(僅大盤有效) 35 WORD m_wDecline; //下跌家數(僅大盤有效) 36 } STKDATA; 37 38 //////////////////////////////////////////////////// 39 //擴展數據,用於描述分筆成交數據的買賣盤 40 //////////////////////////////////////////////////// 41 42 typedef union tagSTKDATAEx 43 { 44 struct 45 { 46 float m_fBuyPrice[3]; //買1--買3價 47 float m_fBuyVol[3]; //買1--買3量 48 float m_fSellPrice[3]; //賣1--賣3價 49 float m_fSellVol[3]; //賣1--賣3量 50 DWORD m_dwToken; //成交方向 51 }; 52 float m_fDataEx[13]; 53 } STKDATAEx; 54 55 //////////////////////////////////////////////////// 56 //除權數據 57 //////////////////////////////////////////////////// 58 59 typedef struct tagSPLITDATA 60 { 61 //timetype m_time; //時間,UCT 62 time_t m_time; 63 float m_fHg; //紅股 64 float m_fPg; //配股 65 float m_fPgj; //配股價 66 float m_fHl; //紅利 67 } SPLITDATA; 68 69 70 //////////////////////////////////////////////////// 71 /*財務數據順序(m_pfFinData內容) 72 73 序號 內容 74 75 0 總股本(萬股), 76 1 國家股, 77 2 發起人法人股, 78 3 法人股, 79 4 B股, 80 5 H股, 81 6 流通A股, 82 7 職工股, 83 8 A2轉配股, 84 9 總資產(千元), 85 10 流動資產, 86 11 固定資產, 87 12 無形資產, 88 13 長期投資, 89 14 流動負債, 90 15 長期負債, 91 16 資本公積金, 92 17 每股公積金, 93 18 股東權益, 94 19 主營收入, 95 20 主營利潤, 96 21 其他利潤, 97 22 營業利潤, 98 23 投資收益, 99 24 補貼收入, 100 25 營業外收支, 101 26 上年損益調整, 102 27 利潤總額, 103 28 稅后利潤, 104 29 凈利潤, 105 30 未分配利潤, 106 31 每股未分配, 107 32 每股收益, 108 33 每股凈資產, 109 34 調整每股凈資, 110 35 股東權益比, 111 36 凈資收益率 112 37 經營現金流入 113 38 經營現金流出 114 39 經營現金流量 115 40 投資現金流入 116 41 投資現金流出 117 42 投資現金流量 118 43 籌資現金流入 119 44 籌資現金流出 120 45 籌資現金流量 121 46 現金及等價物 122 47 應收帳款周轉率 123 48 存貨周轉率 124 49 股東總數 125 50 發行價 126 51 速動比率 127 52 主營業務增長率 128 53 稅后利潤增長率 129 54 凈資產增長率 130 55 總資產增長率 131 */ 132 133 //////////////////////////////////////////////////// 134 //調用參數項結構 135 //////////////////////////////////////////////////// 136 typedef struct tagCALCPARAM 137 { 138 union 139 { 140 const float m_fParam; //數值參數 141 const float* m_pfParam; //序列參數,指向一個浮點型數組 142 const char* m_szParam; //字符串參數 143 }; 144 //序列參數有效起始位置 145 const int m_nParamStart; 146 }CALCPARAM; 147 148 149 //////////////////////////////////////////////////// 150 //調用接口信息數據結構 151 //////////////////////////////////////////////////// 152 typedef struct tagCALCINFO 153 { 154 const DWORD m_dwSize; //結構大小 155 const DWORD m_dwVersion; //調用軟件版本(V2.10 : 0x210) 156 const DWORD m_dwSerial; //調用軟件序列號 157 //const char* m_strUserName; //軟件用戶名 158 const char* m_strStkLabel; //股票代碼 159 const BOOL m_bIndex; //大盤 160 161 const int m_nNumData; //數據數量(pData,pDataEx,pResultBuf數據數量) 162 const STKDATA* m_pData; //常規數據,注意:當m_nNumData==0時可能為 NULL 163 const STKDATAEx* m_pDataEx; //擴展數據,分筆成交買賣盤,注意:可能為 NULL 164 165 const int m_nParam1Start; //參數1有效起始位置 166 const float* m_pfParam1; //調用參數1 167 const float* m_pfParam2; //調用參數2 168 const float* m_pfParam3; //調用參數3 169 const float* m_pfParam4; //調用參數4 170 171 float* m_pResultBuf; //結果緩沖區 172 const int m_dataType; //數據類型 173 const float* m_pfFinData; //財務數據 174 175 //以上與分析家兼容,所以沿用其結構和名稱 176 177 //以下為飛狐交易師擴展 178 179 const DWORD m_dwReserved; // 保留 180 181 const int m_nNumParam; // 調用參數數量 182 const CALCPARAM* m_pCalcParam; // 調用參數數組 183 184 const DWORD m_dwReservedEx[4]; // 保留 185 186 char* m_strStkName; //股票名稱 187 188 SPLITDATA* m_pSplitData; //除權數據 189 int m_nNumSplitData; //除權次數 190 191 } CALCINFO;
上面展示了金魔方的數據結構,數據結構主要是存取金融數據的,下面展示下我們自己定義的函數,這個函數也就是金魔方要調用的函數。
extern "C"__declspec(dllexport) int WINAPI TRADE_FIRST(CALCINFO *pData);
上面的結構體中CALCINFO *pData表示輸入的數據,具體的輸入輸出如下:
/*函數輸入 注1: (與分析家兼容) 1.函數調用參數由m_pfParam1--m_pfParam4帶入,若為NULL則表示該參數無效. 2.當一個參數無效時,則其后的所有參數均無效. 如:m_pfParam2為NULL,則m_pfParam3,m_pfParam4一定為NULL. 3.參數1可以是常數參數或序列數參數,其余參數只能為常數參數. 4.若m_nParam1Start<0, 則參數1為常數參數,參數等於*m_pfParam1; 5.若m_nParam1Start>=0,則參數1為序列數參數,m_pfParam1指向一個浮點型數組, 數組大小為m_nNumData,數據有效范圍為 m_nParam1Start 至 m_nNumData-1. 在時間上m_pData[x] 與 m_pfParam1[x]是一致的 注2: (飛狐交易師擴展) 1.該擴展結構使調用參數在技術上可以是無限數目的,且每個參數都可為數值或序列,由公式中實際的調用參數決定。 2.CALCPARAM結構用於帶入參數信息和實際數據,m_pCalcParam數組大小為m_nNumParam,數據有效范圍為 0 至 m_nNumParam-1. 3.按參數的順序,m_pCalcParam[0]為第一個參數的數據,m_pCalcParam[1]為第二個參數的數據...,為了保持兼容,原m_nParam1Start、m_pfParam1等5個屬性依然有賦值。 4.若 i位置的參數為數值,取用m_pCalcParam[i].m_fParam. 5.若 i位置的參數為序列,取用m_pCalcParam[i].m_pfParam,數組大小為m_nNumData,數據有效范圍為m_pCalcParam[i].m_nParamStart 至 m_nNumData-1. 若m_pCalcParam[i].m_nParamStart<0, 則此數組中無有效數據。 6.由於可以調用多個序列,許多序列的計算可以先在公式中進行,然后作為調用的參數即可。 7.經此擴展,對分析家的DLL依然可以調用、兼容。 */ /////////////////////////////////////////////////////////////////////////////////// /* 函數輸出 __declspec(dllexport) int xxxxxxxx(CALCINFO* pData); 1.函數名稱需全部大寫. 2.函數必須以上述形式聲明,請用實際函數名稱替代xxxxxxxx; 對於C++程序還需包括在 extern "C" { } 括號中. 3.函數計算結果用pData->m_pResultBuf帶回. 4.函數返回-1表示錯誤或全部數據無效,否則返回第一個有效值位置,即: m_pResultBuf[返回值] -- m_pResultBuf[m_nNumData-1]間為有效值. 5.函數名稱長度不能超過15字節,動態連接庫文件名不能超過9字節(不包括擴展名),動態庫名稱不能叫SYSTEM,EXPLORER */
下面看一下我如何在dll主函數中調用相關的輸入與最后的輸出返回值
extern "C"__declspec(dllexport) int WINAPI TRADE_FIRST(CALCINFO *pData) { vector<struct info>value;//存放整合之合的數據點 value.reserve(50000); vector<struct up_down>up_down_value;//存放沒有過濾前的頂,底點 up_down_value.reserve(50000); vector<struct up_down>filter_value;//存放最后的頂和底數據,連成筆 filter_value.reserve(50000); //vector<struct line_series>series;//存放整合之合的數據點,特征序列 //series.reserve(50000); //series.clear(); vector<struct line_series>big_line_series;//存放最后的數據 big_line_series.reserve(50000); big_line_series.clear(); if ( pData->m_pfParam1 && //參數1有效 pData->m_nParam1Start<0 && //參數1為常數 pData->m_pfParam2==NULL ) //僅有一個參數 { float fParam = *pData->m_pfParam1; int flag = (int)fParam; //參數1 while (pData->m_nNumData<4) { return -1; } if(flag>0) { if(pData->m_nNumData<100) return -1; comb_data(pData,value);//進行數據合並,value存儲合並之后的數據 find_up_down(value,up_down_value);//找到頂底數據,存在up_down_value中 filter_up_down(up_down_value,filter_value,value); //過濾數據,找到筆 //feature_series(filter_value,series);//得到所有的向上的特征序列及向下的特征序列 //preidct(filter_value,big_line_series); for(int j=0;j<pData->m_nNumData;j++) { pData->m_pResultBuf[j]=0; } for(int i=0;i<filter_value.size();i++) { pData->m_pResultBuf[filter_value[i].data.node_no]=filter_value[i].data.flag;//返回序列,筆序列 } return 0; } } return -1; }
上面的pData為輸入、輸出數據結構體,在輸入的時候,調用m_pdata數組就可以讀入任意時間段的數據,最后數據返回的時候,再寫入到m_pResult數組中,將結果帶回。至於如何生成dll文件這里就不多講,我采用的是vs2010,編譯直接寫入dll文件中。需要提醒的是,dll文件寫入后要放入金魔方的FmlDll文件中。調試的時候也可以將debug調試器連接到金魔方.exe文件,這樣就可以實時寫入金魔方數據,最后結果也直接帶入到金魔方中進行顯示。