Feed-API(AGVS)


投顧最常用的行情系統,不用一個一個商品訂閱(全部市場的所有交易所商品資訊全收),什麼資料都有... 還真多!


透過Multi-DB稍微分類... 匯市,期貨,選擇權,國際指數,上市櫃股票,權證,興櫃 超過3萬多檔的國內商品一應俱全,還有領先指標!
一直沒注意國內環境,最近才發現居然有行情系統連委買委賣的資料都沒有也能賣耶...然後還會掉Tick或嚴重延遲...囧

3萬多檔的國內商品的Tick就這麼收齊完整了!! 找個熟悉的商品比對一下資料看看~
連最基礎的一檔買賣價量都沒有的行情系統更不用說哪可能看的到五檔十檔呢!
( 迷: 都沒有就會漏和慢了... 有了還得了嗎? 根本不會動 )
聽了一些說辭,或說即時性不重要,委買賣不重要,或說分K就夠了 ... 但一切只是不敢正視技術核心弱的藉口而已!
相比之下這裡測試的這個產品資訊來源,超過10年都沒維護過了,什麼資料都有,所有商品同時接收也沒有漏或慢的問題...(鐵証)

這陣子每天看超過10小時的戲劇台,本週心血來潮利用廣告空檔弄一下這個...
果然輕輕鬆鬆就完成了雛型,再來看需求性要什麼作什麼就更簡單了

台灣的市場還是來點繁體字比較有感覺,調整後也能直接搭配OBG格式轉碼進其他系統了

話說自動交易至少要有這樣水準的報價,不然投顧怎麼會都用這套是吧!
別在呆呆的弄一堆策略,弄來弄去只是單一商品在分析,怎麼玩的贏人家?
都說台指期的依據就是加權了... 加權指數的領先指標當然可以領先一步阿

而下單機至少就是要資料齊全才是! 不然收到訊號才發現缺東缺西然後東補西補,
lag個幾秒就凍鎂佻了,居然還有那種只是幾檔報價還會累格幾分幾十分的...那是要怎麼玩阿?!!
人家說輸在起跑點就是這個意思, 上面這個超過10年都沒進步的產品也能輕鬆勝出耶!

企業空轉的寫照大概就是說全新改版號稱更好的系統結果是比原本舊的還糟糕,
說穿了就是負責技術的變差了,改不動舊的就藉口作新的,管理階層又不懂,不懂就算了還要裝懂,
當然策略方向都不對,然後花了幾年才發現真的不行,但是頭洗下去了,死的也要說成活的...
更多失敗的案例更是為了省一點成本而虧了幾百倍營利...
有時真的很難理解國內那麼多套行情架構,不是慢就是缺(併)還有不穩定的問題...

不論何時Tick就是完整又即時,所以只要用對系統和工具,自然就不會有任何奇奇怪怪的問題


下面是簡單的Feed-API相關程式碼(參考)

只需看 sprintf 和 fnPktEvFeeder_SendPacket

void pushFutCurItemData(void *vpItem)
{//期貨,選擇權
    char caBuffer[8192];
    char *cpBuf = caBuffer;
    L_OptCur_ItemData &item = *(L_OptCur_ItemData *)vpItem;//選擇權與期貨的格式都一樣
    if (item.key.PutCall)
    {//選擇權
        cpBuf = storeFutureSymbol(cpBuf, item.refkey);
        cpBuf += sprintf(cpBuf, "(%c%d)|CCCO", item.key.PutCall, item.key.Strike);
    }
    else
    {//期貨
        if (item.refkey.yr_mon)
        {//期貨
            cpBuf = storeFutureSymbol(cpBuf, item.refkey);
            cpBuf += sprintf(cpBuf, "|CCCF");
        }
        else
        {//現貨
            cpBuf += sprintf(cpBuf, "@r%Xi%X|CCC", item.refkey.route, item.refkey.index);
        }
    }

    if (cpBuf != caBuffer)
    {
        int i;
        L_OptCur_CurStatus &cur = item.data.cur;
        L_OptCur_CurDatas &dat = cur.datas;

        //填入所有想要的報價資料
        cpBuf += sprintf(cpBuf,
            ",92=%s,93=r%X,12=%d,13=%d"
            ",14=%d,6=%d,8=%d,10=%d"
            , cur.SymbolID, item.refkey.route, dat.SettlementPrice, dat.OpenInterest
            , dat.Reference, dat.Open, dat.High, dat.Low
        );
        if (dat.Open)
        {//填入Tick相關的資料
            cpBuf += sprintf(cpBuf,
                ",61=%d,22=%d,27=%d,23=%d"
                , (wwxTime.decimal_CurrTime((time_t *)&(dat.LastTime), true) * 1000), dat.LastPrice, dat.MatchTotalQty, dat.MatchQuantity
            );
        }
        //填入五檔買賣價量
        for (i = 0; i < 5; i++)
        {
            cpBuf += sprintf(cpBuf,
                ",%d=%d,%d=%d,%d=%d,%d=%d"
                , 100+i*2, dat.BuyPrice[i], 101+i*2, dat.BuyQuantity[i]
                , 200+i*2, dat.SellPrice[i], 201+i*2, dat.SellQuantity[i]
            );
        }

        cpBuf++;//含ZE
        fnPktEvFeeder_SendPacket('F', caBuffer, (cpBuf - caBuffer), false);
    }
}

void pushStkCurItemData(void *vpItem)
{//股市,權證
    char caBuffer[8192];
    char *cpBuf = caBuffer;
    L_XnCur_ItemData &item = *(L_XnCur_ItemData *)vpItem;
    L_XnCur_Keys &key = item.keys;
    L_CurStatus_Best5_Map *pBest5 = item.getBest5_Map();
    if (pBest5)
    {//有5檔欄位格式的商品
        int i;

        L_XnCur_CurStatus &cur = item.data.cur;
        L_CurStatus_Best5_unit &b5 = pBest5->best5;
        L_CurStatus_value_amount *spBuyData = b5.bs_data;
        L_CurStatus_value_amount *spSellData = &(b5.bs_data[5]);

        //產生商品全域完整代碼
        cpBuf += sprintf(cpBuf, "@t%X-%X", (key.type_uno.type & 0xFF), key.type_uno.uno);
        if (key.IsSTOCK_TYPE())
            cpBuf += sprintf(cpBuf, "|TSE");
        else if (key.IsOTC_TYPE())
            cpBuf += sprintf(cpBuf, "|OTC");
        else if (key.IsSUBS_TYPE())
            cpBuf += sprintf(cpBuf, "|SUBS");
        else
            cpBuf += sprintf(cpBuf, "|CVS");

        //填入所有想要的報價資料
        cpBuf += sprintf(cpBuf,
            ",92=%s,93=t%X"
            ",14=%d,6=%d,8=%d,10=%d"
            , key.id, key.type_uno.type
            , cur.ref, cur.open, cur.high, cur.low
        );
        if (cur.open)
        {//填入Tick相關的資料
            cpBuf += sprintf(cpBuf,
                ",22=%d,27=%d,23=%d"
                , cur.trade, cur.volume, cur.volinc
            );
        }
        //填入五檔買賣價量
        for (i = 0; i < 5; i++)
        {
            cpBuf += sprintf(cpBuf,
                ",%d=%d,%d=%d,%d=%d,%d=%d"
                , 100+i*2, spBuyData[i].value, 101+i*2, spBuyData[i].amount
                , 200+i*2, spSellData[i].value, 201+i*2, spSellData[i].amount
            );
        }

        cpBuf++;//含ZE
        fnPktEvFeeder_SendPacket('F', caBuffer, (cpBuf - caBuffer), false);
    }
    else if (key.type_uno.type == OCS_TYPE)
    {
        L_XnCur_CurStatusOCS &cur = item.data.ocs;

        //產生商品全域完整代碼
        cpBuf += sprintf(cpBuf, "@t%X-%X|OCS", (key.type_uno.type & 0xFF), key.type_uno.uno);

        //填入所有想要的報價資料
        cpBuf += sprintf(cpBuf,
            ",92=%s,93=t%X"
            ",14=%d,6=%d,8=%d,10=%d"
            ",18=%d,19=%d,20=%d,21=%d"
            , key.id, key.type_uno.type
            , cur.ref, cur.open, cur.high, cur.low
            , cur.buy, cur.buy_vol, cur.sell, cur.sell_vol
        );
        if (cur.open)
        {//填入Tick相關的資料
            cpBuf += sprintf(cpBuf,
                ",22=%d,27=%d,23=%d,13=%d"
                , cur.trade, cur.total_trade_vol, cur.trade_vol, cur.stock_vol
            );
        }

        cpBuf++;//含ZE
        fnPktEvFeeder_SendPacket('F', caBuffer, (cpBuf - caBuffer), false);
    }
}


同樣的,透過Feed-API可以把各種(商品,策略,指標)訊號打入系統,就能完整紀錄Tick轉成歷史資料,
如此可行成獨家衍生商品行情供應需求...
在系統下可以無窮變化將訊號變商品衍生更多指標成為訊號觸發更多連動,
不論多複雜的演算都能輕鬆瞬間完成!

而且都已經物連網時代了耶,訊號透過IP架構的Feed-API不但可以跨主機處理當然也遠比本地用.txt檔或DDE還快!
特殊的TCP通訊設計,不但速度媲美UDP,更能確保所有資訊完整不缺漏!!

好久沒試DDE了,突然想到也來用一下~ 果然還是一樣簡單好用有效率!

跑了N天後還是穩當當... 有空來開直播給大家參考看看!

中秋節海期可沒有放假,看看隔天早上的行情


PS1: 前述xGVS產品是全市場全部商品的資訊完全即時,市面上卻有只訂閱一些商品資訊就有LAG現象的實在令人難以想像阿!
PS2: 是否有想到過Feed-API(Client)可以輕鬆把大量的行情資料打到Sever上完全即時,如果拿來作下單工具可以多誇張嗎?!! 呵呵!


註解