請選擇 進入手機版 | 繼續訪問電腦版

COCO研究院

 找回密碼
 註冊
搜索
查看: 4486|回復: 3

[API] 不用滴滴咿改寫吸嘉嘉感覺好帥(ADK)

[複製鏈接]
發表於 19-1-28 15:15 | 顯示全部樓層 |閱讀模式
上次把模擬資料用DDE打到EXCEL上

再用AmiBroker的Plug-In去收雖然用C#寫蠻簡單的(ptid=145893 #8樓)

但是有個EXCEL有時還是感覺很礙眼,還有DDE的欄位設定囉唆又難看

之前也看ADK說VC6和DevC可以用,只是不知怎麼開始

寫程式總是看別人寫出來後覺得簡單,自己要從頭開始寫都覺得很難

終於孤狗到一個可用的ADK資料,看起來就是和以前舊公司所收藏的到的API有關

總是要有個起頭,想說街口轉1000索討試試看無妨,就收到了網頁所描述神奇的C++專案程式源碼了

先把bin的dll丟進AmiBroker的Plugins的資料夾內,有vc,devc,bcb好幾個版本,先試其中一個32位元的

果然順利在AmiBroker上可以查看到

Plugin查看

Plugin查看


加入新的database觀察看看,確實可以選擇這個資料源

不過這個資料源要載入另一個dll不存在,所以出現訊息提示

就把之前接收模擬資訊源用的dll丟進去AB的安裝資料夾內

重開AB,還是有錯誤,原來是我的dll太舊了

不支援功能的訊息

不支援功能的訊息

原來是dll版本太舊的樣子

原來是dll版本太舊的樣子


不過上面的種種現象說明這個ADK開發的plugin是可以運作的,所以就來研究程式碼吧!

因為這份ADK的IDE有很多版,想說就在這台AB的測試虛機中下載了小小的DevC

這個不用安裝,硬碟只吃60MB,把專案一開,居然是這樣寫

DevC的ADK專案

DevC的ADK專案


最重要的是按了編譯就真的出來新的dll了,這也表示值得花時間看下去

這個看下去我看了很久,看了好多天就不用說出來笑了

重點是我改成功了,看影片
AB-RealtimeADK.rar (38.98 KB, 下載次數: 18, 售價: 1 金錢)

雖然手上收行情的api比較舊還是可以用的啦! 程式裏不要調用新功能就可以了

看一下報價畫面

看一下報價畫面


看別人的程式真的好簡單,註解比程式碼還多全部一起算

ADK的部分不到400行,收行情的部分也300多行而已

如果之前在舊公司有備份到feed server就好了,不管券商行情多難用都可以變簡單

之後我也想試試x64是否也行,又下了DevC5也是可攜版(不用安裝)不過很大要360MB

果然也是順利編譯x86和x64的版本,後來拿去另一邊有VC10的試,也是都不用改

選Win32就邊出x32的版,選x64就編譯出x64的版,把自己編譯的都拿去試過AB全部OK

裡面還有BCB5和BCB6的版,裡面附有一個小工具,只要BCB編譯後用小工具處理過AB就也可以使用

不過我沒有BCB可以試,就不知道是怎樣的情況了

結論是          還蠻好玩的         比接DDE直接方便  比寫C#帥

ADK的程式碼像這樣,提到舊版的地方就是我修改過的
  1. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //ADK的基本定義與宣告
  3. #ifndef _USRDLL
  4.         #define _USRDLL                /*        注意! 用ADK的 Plugin.h 來寫dll的話要設立此 define , VC專案是會自動設立        */
  5. #endif

  6. #include "../Plugin.h"        //官方原始檔案, 碰都不用碰就能爽爽用
  7. //#include "../Plugin_Legacy.h"        //若需支援老舊的AmiBroker可透過此定義檔做轉換 ( Plugin.h 裡面直接有include )

  8. //#include "Data_DbfTCdll2.cpp"        // 使用 DbfTCdll2 連接 DTS (HFOCX範例), 想用其他資料來源換掉這行即可
  9. #include "Data_DbfTCdll2(KGQ).cpp"        //因為是舊版的,少了Tick Manager功能,改寫在這個cpp嘗試

  10. //以下為ADK相關, 這個檔以ADK功能為主
  11. //-----------------------------------------------------------------------------------------------------------------
  12. // These are the only two lines you need to change
  13. #define PLUGIN_NAME "FTW-DbfTCdll2"        // "?RT data Plug-in"        //"Sample AmiBroker Plug-in"
  14. #define VENDOR_NAME "ftw.tw"        // "Amibroker.com"
  15. #define PLUGIN_VERSION 10000
  16. #define PLUGIN_ID PIDCODE( 'F', 'T', 'W', 'D' )        //在AmiBroker的全部Plug-in中需為unique,若需多個相同方式的dll改這裏不一樣即可

  17. #define THIS_PLUGIN_TYPE PLUGIN_TYPE_DATA        //設成為資料源模式( Chart-Data or real-time , Tick資料也是比照Chart-Data要生給AB抓而不是AB自己會累積產生)
  18. /*        // PLUGIN_TYPE Note!!
  19. 詳見 ADK/adk.html                1.2 INTERFACE ARCHITECTURE
  20. 基本上 AmiBroker 判斷PLUGIN是否有提供以下介面函式
  21.         GetQuotesEx - 歷史數據(chart-data) ... 會來撈一個array的歷史資料(如KD) (Tick也是要這樣處理)
  22.         GetRecentInfo - 即時數據(real-time) ... 會來撈報價如 trade, bid/ask, days high/low, etc...

  23. #define PLUGIN_TYPE_AFL 1                        //PLUGIN_TYPE_AFL 功能模式吧... 好像只是提供一些功能方便於AmiBroker取值
  24.         For AFL plugins this second initialization phase happens when AFL engine starts
  25.          for a very first time initializing its function table. Then AmiBroker performs the following operations:
  26.                 AmiBroker calls SetSiteInterface() function exported by the plug in. The site interface is used later in DLL for calling back various AmiBroker functions (including allocating/freeing memory, reading/writing AFL variables, calling back AFL functions)
  27.                 AmiBroker calls Init() function from the plug in DLL that should be used for initializing working variables/allocating extra memory if necessary
  28.                 AmiBroker calls GetFunctionTable() from the plug in DLL. In this step the AFL functions provided by the DLL are added to the internal AmiBroker dispatch tables allowing futher calls of these functions.
  29.         Note that this is done only once after loading DLLs in the newer versions of AmiBroker (4.10 and up).

  30. #define PLUGIN_TYPE_DATA 2                        //PLUGIN_TYPE_DATA 資料源模式, 於AmiBroker中會出現在 Data Source 中可以選擇
  31.         1.需提供 SetTimeBase 回應 AmiBroker 可接受什麼時間間隔等級的資料
  32.         2.可透過 GetStatus 讓 AmiBroker 知道資料源的連線狀況 且會於介面右下角顯示對應的狀態與訊息
  33.         3.當於AmiBroker的選單進入 File->Database Settings 選擇此資料源確認後, 就會呼叫 GetQuotesEx
  34.          (a)如果是舊版的AmiBroker則是呼叫 GetQuotes 如不想支援舊版可以不用設計 GetQuotes
  35.          (b)若要支援舊版的AmiBroker可以透過 Plugin_Legacy.h 的定義和新格式做轉換
  36.          (c)於AmiBroker的選單進入 Symbol->New 新建一個商品代碼時確定後也會呼叫 GetQuotesEx
  37.          (d)可透過 ::SendMessage( g_hAmiBrokerWnd, WM_USER_STREAMING_UPDATE, 0, 0 ); 的方式通知AmiBroker呼叫 GetQuotesEx 更新資料

  38.         For Data plugins the second initialization phase happens when given data source is selected
  39.          for the very first time in current AmiBroker session.
  40.         Then AmiBroker just calls Init() function from the plugin that should be used for initializing working variables/allocating extra memory if necessary.
  41.         No other function is called for data plugins at this time.

  42. #define PLUGIN_TYPE_AFL_AND_DATA 3
  43.         看就明白這是 AFL + DATA 混合的模式

  44. #define PLUGIN_TYPE_OPTIMIZER 4
  45. */

  46. /*        // real-time 注意這幾個
  47. GetPluginStatus() function is optional and used mostly by real-time plugins to provide visual feedback on current plugin status. It provides a way to display status information in the AmiBroker's status bar. For example implementation of GetPluginStatus() function please check QuoteTracker plugin source.

  48. The following two functions are implemented only by real-time plugins:

  49. PLUGINAPI struct RecentInfo * GetRecentInfo( LPCTSTR pszTicker ); // RT plugins    only
  50. PLUGINAPI int GetSymbolLimit( void ); // RT plugins only

  51. GetRecentInfo() function is exported only by real-time plugins and provides the information about the most recent trade, bid/ask, days high/low, etc (updated by streaming data).
  52. It is called by AmiBroker's real-time quote window on each window refresh (occurs several times a second). The function takes ticker symbol and returns the pointer to RecentInfo structure described above.

  53. GetSymbolLimit() function is exported only by real-time plugins.
  54. It returns the maximum number of streaming symbols that plugin and/or external data source can handle.
  55. The result of this function is used to limit the number of symbols that are displayed in real-time quote window
  56. */

  57. ////////////////////////////////////////
  58. // Data section
  59. ////////////////////////////////////////
  60. static struct PluginInfo oPluginInfo =
  61. {
  62.                 sizeof( struct PluginInfo ),
  63.                 THIS_PLUGIN_TYPE,               
  64.                 PLUGIN_VERSION,
  65.                 PLUGIN_ID,
  66.                 PLUGIN_NAME,
  67.                 VENDOR_NAME,
  68.                 0,                // certificate code - set it to zero for private plug-ins
  69.                 527000        // 這裡設計只用新版的 GetQuotesEx 不再用舊的 GetQuotes 所以限制要求最低版本要AmiBroker 5.27以上
  70. };

  71. // the site interface for callbacks
  72. struct SiteInterface gSite;

  73. enum {
  74. //用來表示資訊源狀態
  75.         STATUS_WAIT,
  76.         STATUS_CONNECTED,
  77.         STATUS_DISCONNECTED,
  78.         STATUS_SHUTDOWN
  79. };
  80. int                g_nStatus = STATUS_SHUTDOWN;


  81. ///////////////////////////////////////////////////////////
  82. // Basic plug-in interface functions exported by DLL
  83. ///////////////////////////////////////////////////////////

  84. ///////////////////////////////////////////////////
  85. // COMMON EXPORTED FUNCTONS
  86. //
  87. // Each AmiBroker plug-in DLL must export the following
  88. // functions:
  89. // 1. GetPluginInfo        - called when DLL is loaded
  90. // 2. Init - called when AFL engine is being initialized
  91. // 3. Release - called when AFL engine is being closed

  92. PLUGINAPI int GetPluginInfo( struct PluginInfo *pInfo )
  93. {
  94.         *pInfo = oPluginInfo;

  95.         return TRUE;
  96. }


  97. /*        // for 設計 PLUGIN_TYPE_DATA 所以不需要這個
  98. // SiteInterface structure <== 回callAmiBroker的內建函式透過此結構 看.h檔內容 "Plugin.h"
  99. // defines call-back function pointers
  100. // the structure is filled with correct
  101. // pointers by the AmiBroker and passed to DLL via SetSiteInterface() function call
  102. //
  103. // SiteInterface is used as a way to call-back AmiBroker built-in functions
  104. //
  105. PLUGINAPI int SetSiteInterface( struct SiteInterface *pInterface )
  106. {
  107.         gSite = *pInterface;

  108.         return TRUE;
  109. }
  110. */

  111. PLUGINAPI int Init(void)
  112. {
  113.         if (!hmDbfTCdll)
  114.                 hmDbfTCdll = LoadLibrary(DbfTCdllLibSource);
  115.         if (hmDbfTCdll)
  116.         {
  117.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_SelectDataSet);
  118.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_InitUser);
  119.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_Start);
  120.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_Stop);
  121.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_GetConnectionStatus);
  122.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_CallBack_Register);
  123.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_GetCurrTagValue);
  124.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_GetPrevTagValue);
  125.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_CreateStringIdMapping);
  126.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_GetStringId);
  127.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_CreateItemQuoteMemory);
  128.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_GetItemQuoteMemory);
  129.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_GetQueueCount);

  130. /*
  131.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_STManCreateGroup);
  132.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_STManCreateProduct);
  133.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_STManGetTickHandle);
  134.                 WWXfunc_DllImport(hmDbfTCdll, fnDbfTCdll_STManGetTickMemory);
  135. */                //舊版的沒這個只能先拿掉

  136.                 if (fnDbfTCdll_CallBack_Register)
  137.                 {
  138.                         //CallBack 模式
  139.                         fnDbfTCdll_CallBack_Register(TagDataProcessFunction, 1);// 1 - By Tag, 每個商品的每個Tag更新都會呼叫
  140.                         fnDbfTCdll_CallBack_Register(ItemProcessFunction, 2);// 2 - By Item, 有更新的商品會呼叫 (傳入之cpVarName,cpNewValue,cpOldValue等參數為NULL)
  141. /*
  142.                         if (fnDbfTCdll_STManCreateGroup)
  143.                         {
  144.                                 unsigned long uGroupIndex = fnDbfTCdll_STManCreateGroup("RecentInfoDataItem", sizeof(RecentInfoDataItem), NULL, 64, 256);
  145.                                 unsigned long uProductIndex = fnDbfTCdll_STManCreateProduct(uGroupIndex);
  146.                                 vpQuoteIndexHandle = fnDbfTCdll_STManGetTickHandle(uGroupIndex, uProductIndex);
  147.                                 if (!vpQuoteIndexHandle)
  148.                                         MessageBox(0, "Dll file "DbfTCdllLibSource" STMan Err! Memory crash!!", PLUGIN_NAME" Init Error!", MB_OK);
  149.                         }
  150.                         else
  151.                                 MessageBox(0, "Dll file "DbfTCdllLibSource" not support STMan", PLUGIN_NAME" Init Error!", MB_OK);
  152. */                //舊版的沒這個只能先拿掉
  153.                 }
  154.                 else
  155.                 {
  156.                         FreeLibrary(hmDbfTCdll);
  157.                         hmDbfTCdll = NULL;
  158.                         MessageBox(0, "Dll file "DbfTCdllLibSource" load faild!!", PLUGIN_NAME" Init Error!", MB_OK);
  159.                 }
  160.         }
  161.         else
  162.         {
  163.                 MessageBox(0,
  164.                         "Dll file "DbfTCdllLibSource" not found!!\n"
  165.                         "請將檔案置於AmiBroker的工作環境資料夾內"
  166.                         , PLUGIN_NAME" Init Error!"
  167.                         , MB_OK
  168.                 );
  169.         }

  170.         if (hmDbfTCdll)
  171.         {
  172.                 fnDbfTCdll_InitUser(PLUGIN_NAME);        // 直接用PLUGIN_NAME當User,同一資訊源相同User只能一個在線; 可改成用參數提供設定
  173.                 fnDbfTCdll_SelectDataSet(caDB_list);
  174.                 if (fnDbfTCdll_Start(caDTS_host))
  175.                         g_nStatus = STATUS_WAIT;
  176.         }

  177.         return 1; // default implementation does nothing

  178. };         

  179. PLUGINAPI int Release(void)
  180. {
  181.         if (hmDbfTCdll)
  182.                 fnDbfTCdll_Stop();

  183.         return 1; // default implementation does nothing
  184. };


  185. HWND g_hAmiBrokerWnd = NULL;

  186. /////////////////////////////////
  187. // Forward declaration of Timer callback function
  188. //////////////////////////////////
  189. //VOID CALLBACK OnTimerProc( HWND, UINT, UINT_PTR, DWORD );


  190. ///////////////////////////////////////
  191. // Notify function implementation
  192. //
  193. // Notify() is called by AmiBroker
  194. // in the various circumstances including:
  195. // 1. database is loaded/unloaded
  196. // 2. right mouse button is clicked in the
  197. //    plugin status area of AmiBroker's status bar.
  198. //
  199. // The implementation may provide special handling
  200. // of such events.
  201. ///////////////////////////////////////

  202. PLUGINAPI int Notify(struct PluginNotification *pn)
  203. {
  204.         //AFX_MANAGE_STATE( AfxGetStaticModuleState() );

  205.         if( g_hAmiBrokerWnd == NULL )
  206.         {
  207.                 g_hAmiBrokerWnd = pn->hMainWnd;

  208.                 if (pn->nReason & REASON_DATABASE_LOADED)
  209.                 {//Amibroker已經準備好接收資料
  210.                         //::MessageBox(0, "REASON_DATABASE_LOADED", "STATUS_CONNECTED", MB_OK);
  211.                 }

  212.                 //if (pn->nReason & REASON_DATABASE_UNLOADED)
  213.                 //{
  214.                 //        ::MessageBox(0, "REASON_DATABASE_UNLOADED", NULL, MB_OK);
  215.                 //}

  216.                 //if (pn->nReason & REASON_STATUS_RMBCLICK)
  217.                 //        ::MessageBox(0, "REASON_STATUS_RMBCLICK", NULL, MB_OK);
  218.         }

  219.         return 1;
  220. }         


  221. ////////////////////////////////////////
  222. // GetStatus function is called periodically
  223. // (in on-idle processing) to retrieve the status of the plugin
  224. // Returned status information (see PluginStatus structure definition)
  225. // contains numeric status code        as well as short and long
  226. // text descriptions of status.
  227. //
  228. // The highest nibble (4-bit part) of nStatus code
  229. // represents type of status:
  230. // 0 - OK, 1 - WARNING, 2 - MINOR ERROR, 3 - SEVERE ERROR
  231. // that translate to color of status area:
  232. // 0 - green, 1 - yellow, 2 - red, 3 - violet

  233. PLUGINAPI int GetStatus( struct PluginStatus *status )
  234. {
  235.         char *cpStatus = "GetConnectionStatus() failed!";
  236.         if (hmDbfTCdll)
  237.         {
  238.                 cpStatus = fnDbfTCdll_GetConnectionStatus();
  239.                 if (cpStatus[1] == 'O')
  240.                         g_nStatus = STATUS_CONNECTED;
  241.                 else if (cpStatus[1] == 'X')
  242.                         g_nStatus = STATUS_DISCONNECTED;
  243.                 else
  244.                         g_nStatus = STATUS_WAIT;
  245.         }

  246.         switch( g_nStatus )
  247.         {
  248.         case STATUS_WAIT:
  249.                 status->nStatusCode = 0x10000000;
  250.                 strcpy( status->szShortMessage, "WAIT" );
  251.                 strcpy( status->szLongMessage, cpStatus );
  252.                 status->clrStatusColor = RGB( 255, 255, 0 );
  253.                 break;
  254.         case STATUS_CONNECTED:
  255.                 status->nStatusCode = 0x00000000;
  256.                 strcpy( status->szShortMessage, "OK" );
  257.                 strcpy( status->szLongMessage, vpQuoteIndexHandle?cpStatus:DbfTCdllLibSource"api too old " );
  258.                 status->clrStatusColor = RGB( 0, 255, 0 );
  259.                 break;
  260.         case STATUS_DISCONNECTED:
  261.                 status->nStatusCode = 0x20000000;
  262.                 strcpy( status->szShortMessage, "ERR" );
  263.                 strcpy( status->szLongMessage, cpStatus );
  264.                 status->clrStatusColor = RGB( 255, 0, 0 );
  265.                 break;
  266.         case STATUS_SHUTDOWN:
  267.                 status->nStatusCode = 0x30000000;
  268.                 strcpy( status->szShortMessage, "DOWN" );
  269.                 strcpy( status->szLongMessage, "Connection is shut down.\nThe dll file '"DbfTCdllLibSource"' can't load." );
  270.                 status->clrStatusColor = RGB( 192, 0, 192 );
  271.                 break;
  272.         default:
  273.                 strcpy( status->szShortMessage, "Unkn" );
  274.                 strcpy( status->szLongMessage, cpStatus );
  275.                 status->clrStatusColor = RGB( 255, 255, 255 );
  276.                 break;
  277.         }

  278.         return 1;
  279. }

  280. PLUGINAPI int SetTimeBase( int nTimeBase )
  281. {
  282. //char txt[128];
  283. //sprintf(txt, "%d", nTimeBase);
  284. //::MessageBox(0, "SetTimeBase", txt, MB_OK);
  285.         //return ( nTimeBase >= 60 && nTimeBase <= ( 24 * 60 * 60 ) )  ? 1 : 0;        //1分線 ~ 日線
  286.         return ( nTimeBase >= 0 && nTimeBase <= ( 24 * 60 * 60 ) )  ? 1 : 0;        // Ticker ~ 日線
  287. }

  288. //ADK for RT
  289. //-----------------------------------------------------------------------------------------------------------------
  290. ////////////////////////////////////////
  291. // GetSymbolLimit function is called by AmiBroker
  292. // to find out the maximum number of real-time streaming symbols
  293. // that can be displayed in the real-time quote window.
  294. ///////////////////////////////////////
  295. // GetSymbolLimit function is optional, used only by real-time plugins
  296. PLUGINAPI int GetSymbolLimit( void )
  297. {//告知AmiBroker, 可以向本plugin註冊最多幾個symbol
  298.         if (hmDbfTCdll)
  299.                 return 99999;
  300.         return 0;
  301. }

  302. // GetRecentInfo function is optional, used only by real-time plugins
  303. PLUGINAPI struct RecentInfo * GetRecentInfo( LPCTSTR pszTicker )
  304. {//HFOCX可用的代碼可以看這裏==> http://hfocx.dm.ftw.tw/0025/?Quote=All&xml=1
  305.         if (hmDbfTCdll)
  306.         {
  307.                 RecentItemRefer *spRecentRefer = GetRecentItemRefer(pszTicker);
  308.                 if (spRecentRefer)
  309.                         return &(spRecentRefer->spRecentItem->sRecentInfo);
  310.         }
  311.         return NULL;
  312. }


  313. BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
  314. {
  315.     switch (ul_reason_for_call)
  316.         {
  317.                 case DLL_THREAD_ATTACH:
  318.                 case DLL_THREAD_DETACH:
  319.                         break;

  320.                 case DLL_PROCESS_ATTACH:
  321.                         break;

  322.                 case DLL_PROCESS_DETACH:
  323.                         break;
  324.     }

  325.     return TRUE;
  326. }
複製代碼




 樓主| 發表於 19-1-29 09:34 | 顯示全部樓層
kuolung 發表於 19-1-28 20:56
最核心的 getquoteex 的程式沒 show 出來

WOW
kuolung大來出考題了

不過這比較像是考我的抄襲能力耶

其實像上次用EXCEL作皮看報價,現在換用AB作皮而已

如果會收行情,收行情那塊就能把需要的資料都弄齊也能寫檔不會有什麼問題

也就是收行情本身也是能獨立運作的,AB是平行作業再收一份行情

這樣收行情與存檔的部分才不會因為AB要開開關關而受影響

看kuolung大也是另寫server,AB則透過server收行情與回補這也是相同的概念吧!

模擬資訊源那種行情源原本就有TickWriter可紀錄Tick,

要組成各種cycle的KD或轉成歷史也都沒什麼問題

所以如果存檔就在AB跑的PC上,那GetQuotesEx就是讀檔回補就可以了

很多情況下我只有想要報價而已,歷史對我來說沒什麼意義

在這裡就表現一下程式大概怎麼寫的想法,不然太過累贅就又不好讀了

以網路這份資料 webrtqt.fortunengine.com.tw/rtdata/k-chart/day-2330.txt 存檔作示範

用之前nes大那個CsvReader的dll,抄這份程式碼的作法

弄成很獨立完整加入就可以用的程式碼,像這樣(原本ADK的註解也保留)

  1. typedef long (WINAPI *pWWXfunc_demoTest_LoadFile)(char *TxtFile);
  2. static char WWXfunc_demoTest_LoadFile[] = "demoTest_LoadFile";/* DLL中對應的API名稱 */

  3. typedef long (WINAPI *pWWXfunc_demoTest_ParserCsvLine)(long LineNo);
  4. static char WWXfunc_demoTest_ParserCsvLine[] = "demoTest_ParserCsvLine";/* DLL中對應的API名稱 */

  5. typedef char * (WINAPI *pWWXfunc_demoTest_GetField)(long FieldIndex);
  6. static char WWXfunc_demoTest_GetField[] = "demoTest_GetField";/* DLL中對應的API名稱 */

  7. //啟用指定函數
  8. WWXfunc_DllFuncAdd(demoTest_LoadFile)
  9. WWXfunc_DllFuncAdd(demoTest_ParserCsvLine)
  10. WWXfunc_DllFuncAdd(demoTest_GetField)

  11. #define CsvReadDllLibSource "CsvReader_x32.dll"

  12. HMODULE hmCsvRead = NULL;

  13. //////////////////////////////////////
  14. // GetQuotesEx is a most important function
  15. // for every data plugin
  16. // it is called by AmiBroker everytime AmiBroker
  17. // needs new data for given symbol.
  18. //
  19. // Internally AmiBroker caches response obtained
  20. // from GetQuotes function but you may force it to
  21. // get new data by sending appropriate message to AmiBroker
  22. // main window.
  23. //
  24. //
  25. // When AmiBroker calls GetQuotes function it allocates
  26. // array of quotations of size equal to default number of bars as set in
  27. // File->Database Settings,
  28. // and fills the array with quotes that are already present in the
  29. // database.
  30. // Filled area covers array elements from zero to nLastValid
  31. //
  32. // In your DLL you can update the array with more recent quotes.
  33. // Depending on the data source you can either fill entire array
  34. // from the scratch (Metastock, TC2000, QP2 plugins do that)
  35. // or just add/update a few recent bars and leave the remaining bars
  36. // untouched (eSignal, myTrack, QuoteTracker plugins do that)

  37. // GetQuotesEx function is functional equivalent fo GetQuotes but
  38. // handles new Quotation format with 64 bit date/time stamp and floating point volume/open int
  39. // and new Aux fields
  40. // it also takes pointer to context that is reserved for future use (can be null)
  41. // Called by AmiBroker 5.27 and above
  42. PLUGINAPI int GetQuotesEx( LPCTSTR pszTicker, int nPeriodicity, int nLastValid, int nSize, struct Quotation *pQuotes, GQEContext *pContext  )
  43. {
  44.         //AFX_MANAGE_STATE( AfxGetStaticModuleState() );

  45.         if (!hmCsvRead)
  46.         {
  47.                 hmCsvRead = LoadLibrary(CsvReadDllLibSource);
  48.                 if (hmCsvRead)
  49.                 {
  50.                         WWXfunc_DllImport(hmCsvRead, demoTest_LoadFile);
  51.                         WWXfunc_DllImport(hmCsvRead, demoTest_ParserCsvLine);
  52.                         WWXfunc_DllImport(hmCsvRead, demoTest_GetField);
  53.                 }
  54.         }//這段載入dll對應api的部分應該寫在Init()那邊就好,放這邊是便於看懂關聯性

  55.         if (strcmp(pszTicker, "2330"))
  56.                 return 0;

  57.         if (hmCsvRead)
  58.         {
  59.                 if (nLastValid < 0)
  60.                 {
  61.                         long LineCount = demoTest_LoadFile("2330.txt.csv");
  62.                         if (nSize > LineCount)
  63.                         {
  64.                                 long i;
  65.                                 for (i = LineCount; --i > 0; )
  66.                                 {
  67.                                         if (demoTest_ParserCsvLine(i) > 7)//IndexDate,Date,Open,High,Low,Close,Volume
  68.                                         {
  69.                                                 int year,mon,day;
  70.                                                 if (sscanf(demoTest_GetField(1), "%04d/%02d/%02d", &year, &mon, &day) == 3)
  71.                                                 {
  72.                                                         nLastValid = atol(demoTest_GetField(0)) - 1;
  73.                                                         //pQuotes[ nLastValid ].DateTime.Date;

  74.                                                         //時間
  75.                                                         pQuotes[ nLastValid ].DateTime.Date                = DAILY_MASK; // EOD
  76.                                                         struct PackedDate &DateTime = pQuotes[ nLastValid ].DateTime.PackDate;
  77.                                                         DateTime.Year                = year;
  78.                                                         DateTime.Month                = mon;
  79.                                                         DateTime.Day                = day;
  80.                                                         DateTime.Hour                = 14;
  81.                                                         DateTime.Minute                = 30;
  82.                                                         DateTime.Second                = 0;
  83.                                                         DateTime.MilliSec        = 0;
  84.                                                         DateTime.MicroSec        = 0;

  85.                                                         //KD
  86.                                                         Set_float(pQuotes[ nLastValid ].Open        , demoTest_GetField(2)        );
  87.                                                         Set_float(pQuotes[ nLastValid ].High        , demoTest_GetField(3)        );
  88.                                                         Set_float(pQuotes[ nLastValid ].Low                , demoTest_GetField(4)        );
  89.                                                         Set_float(pQuotes[ nLastValid ].Price        , demoTest_GetField(5)        );
  90.                                                         //pQuotes[ nLastValid ].OpenInterest;
  91.                                                         Set_float(pQuotes[ nLastValid ].Volume        , demoTest_GetField(6)        );
  92.                                                         //pQuotes[ nLastValid ].AuxData1;
  93.                                                         //pQuotes[ nLastValid ].AuxData2;
  94.                                                 }
  95.                                         }
  96.                                 }
  97.                                 return ++nLastValid;
  98.                         }
  99.                 }
  100.         }
  101.         return 0;
  102. }
複製代碼

於AB上出來就是這樣

2330 2019-09-28收盤

2330 2019-09-28收盤


由DataWindow對照網頁內容
IndexDateDateOpenHighLowCloseVolume
15
2017/2/2
188
188.5
184
184.5
153703
右邊紅色的的量是最後一根(2019-01-28)
IndexDateDateOpenHighLowCloseVolume
510
2019/1/28
229.5
229.5
228
229
25986

其實這裡並不難,如果收行情那裡就直接用ADK的struct Quotation格式保存了資料

那GetQuotesEx可能就也只是以assign為主,頂多考慮各種KD是否要在這裡組出來

就像行情那裡也是,因為收行情那裡直接用ADK的struct RecentInfo保存資料,

所以GetRecentInf簡單成這樣
  1. PLUGINAPI struct RecentInfo * GetRecentInfo( LPCTSTR pszTicker )
  2. {
  3.         if (hmDbfTCdll)
  4.         {
  5.                 RecentItemRefer *spRecentRefer = GetRecentItemRefer(pszTicker);
  6.                 if (spRecentRefer)
  7.                         return &(spRecentRefer->spRecentItem->sRecentInfo);
  8.         }
  9.         return NULL;
  10. }
複製代碼

考慮線圖Tick進來則大概是這樣的作法,在行情這邊通知AB來重撈資料
  1. PLUGINAPI struct RecentInfo * GetRecentInfo( LPCTSTR pszTicker )
  2. {
  3.         if (bTickNotify)
  4.         {
  5.                 bTickNotify = false;
  6.                 PostMessage( g_hAmiBrokerWnd, WM_USER_STREAMING_UPDATE, 0, 0 );
  7.         }

  8.         if (hmDbfTCdll)
  9.         {
  10.                 RecentItemRefer *spRecentRefer = GetRecentItemRefer(pszTicker);
  11.                 if (spRecentRefer)
  12.                         return &(spRecentRefer->spRecentItem->sRecentInfo);
  13.         }

  14.         return NULL;
  15. }
複製代碼

東抄西抄的...這份作業花了我好多時間阿


發表於 19-1-29 10:49 | 顯示全部樓層
高手推,不過標題讓我以為這篇文是什麼怪怪的東西  
發表於 19-1-30 22:51 | 顯示全部樓層
kuolung 發表於 19-1-30 07:31
我那是出考題啊 我只最近被群益的 skcom.dll 害慘了 想回來用 元大的 想說有人已經寫好了 就不用自己傷腦 ...

我還要感謝您提供了群益的 skcom.dll ,讓我可以去玩[API] 群益 API 2.13.9 C# 實作 。這畫面就是美呀,看起來好專業!


群益 API 2.13.9 C# 實作

群益 API 2.13.9 C# 實作
您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

手機版|Archiver|站長信箱|廣告洽詢|COCO研究院

GMT+8, 24-3-29 20:53

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回復 返回頂部 返回列表
理財討論網站 | AI繪圖AI超擬真美女AI beauty AI Stable DiffusionAI正妹AI Lookbook