ram 發表於 18-8-1 14:25

傑克請問上次那個QM只有2行是要怎麼用阿?!

本帖最後由 ram 於 18-8-1 15:44 編輯

凡是進入到需要I/O的階段,使用結構總是少不了的必備技能

而不管是通訊,檔案存取,API調用...都算是I/O

上次令我嚇傻的那個QM化作C#長這樣,只有2行
public static extern IntPtr dllCreateItemQuoteMemory(string DBName, string cpItemName, IntPtr vpStructData, int iStructSize);

public static extern IntPtr dllGetItemQuoteMemory(string DBName, string cpItemName);原始的API說明是這樣
//--------------------------------------------------------------------------------------------------------
/* Quote-Manager 功能 */      //須有支援的API版本才提供

//fnDbfTCdll_CreateItemQuoteMemory ==> 產生一個商品所需的記憶體結構對應空間
//      vpStructData : 可放好預設值,作為初值內容
typedef DBFTCDLL_API void * (DBFTCDLLAPI *pWWXfunc_fnDbfTCdll_CreateItemQuoteMemory)(const char *cpDBName, const char *cpItemName, const void *vpStructData, int iStructSize);
static char WWXfunc_fnDbfTCdll_CreateItemQuoteMemory[] = "_fnDbfTCdll_CreateItemQuoteMemory@16";//DLL中對應的API名稱

//fnDbfTCdll_GetItemQuoteMemory ==> 取得商品記憶體結構對應空間
typedef DBFTCDLL_API void * (DBFTCDLLAPI *pWWXfunc_fnDbfTCdll_GetItemQuoteMemory)(const char *cpDBName, const char *cpItemName);
static char WWXfunc_fnDbfTCdll_GetItemQuoteMemory[] = "_fnDbfTCdll_GetItemQuoteMemory@8";//DLL中對應的API名稱

所以上次娶回的西夏婆可以這樣打扮

首先設計結構,就是自己想,需要怎樣的一筆紀錄來作資料保存

估阿估阿,擬下了這樣的內容,這裏就不收治裝費了{:4_186:}   
    public struct PriceField20
    {//固定大小為20 bytes的價位資料空間,為用於像是有小數點的市場選擇使用string以便忠於源汁源味
      
      public string data;
    }

   
    public struct DataField32
    {//固定大小為32 bytes的資料空間
      
      public string data;
    }

   
    public struct PQdataField
    {//便於如買賣價量成對的設計
      public PriceField20 price;
      public Int32 qty;
    }

   
    public struct KDdataField
    {//便於KD的應用設計
      public Int32 timeKey;
      public Int64 Volume;
      public PriceField20 Refer;//參考價
      public PriceField20 Open;//開
      public PriceField20 High;//高
      public PriceField20 Low;//低
      public PriceField20 Close;//收
    }

   
    public struct ItemDatas
    {
      public DataField32 Symbol;//存放來源的代碼

      public DataField32 MySymbol;//自己要用的命名(可於第一次產生時依自己需求設計對應,例如下單的代碼)

      public Int64 Volume;//總量
      public PQdataField Last;//最新成交價和單量

      
      public PriceField20[] aPrice;//可放多個(這裡是設20)價位資料,例如 參考價,開,高,低 ...

      
      public PQdataField[] aBestBuy;//最佳10檔買價量

      
      public PQdataField[] aBestSell;//最佳10檔賣價量

      
      public KDdataField[] aKD_Day;//可放最近10日的日線資料

      //
      //public KDdataField[] aKD_Min;//可放一日的分線資料

      public ItemDatas(string symbol) //建構,用於產生第一次的C#實體空間結構
      {
            Symbol.data = symbol;
            MySymbol.data = "";
            Volume = 0;
            Last.price.data = "";
            Last.qty = 0;
//array的部分要比照前面的規劃new出所需的大小
            aPrice = new PriceField20;
            aBestBuy = new PQdataField;
            aBestSell = new PQdataField;
            aKD_Day = new KDdataField;
            //aKD_Min = new KDdataField;
      }
    }

再來有一個重點,腰要束緊才好看
      // Initialize unmanged memory to hold the struct.
      public static ItemDatas sItemDatas = new ItemDatas("(null)");//C#中為了SizeOf還是要建一個固定的比較方便
      public static IntPtr pItemDatas = Marshal.AllocHGlobal(Marshal.SizeOf(sItemDatas));//可便於指標方式的操作(這個可以不用)

然後就看心情上下其手了,把上次要打DDE資料那邊這樣加料
      public static void ItemProcessCallback(string DBName, string VarName, string Symbol, string NewValue, string OldValue)
      {
            DataCounting++;//程式啟動後資料更新次數

            IntPtr PtrItem = dllGetItemQuoteMemory(DBName, Symbol);
            if (PtrItem == IntPtr.Zero) //if (PtrItem.ToPointer() == null)
            {//尚未存在,建立
                PtrItem = dllCreateItemQuoteMemory(DBName, Symbol, pItemDatas, Marshal.SizeOf(sItemDatas));//這裡pItemDatas不可以用null
                //PtrItem = dllCreateItemQuoteMemory(DBName, Symbol, IntPtr.Zero, Marshal.SizeOf(sItemDatas));
                if (PtrItem != IntPtr.Zero) //if (PtrItem.ToPointer() != null)
                {
                  ItemDatas s = new ItemDatas(Symbol);
                  s.aPrice.data = dllReturnString(dllGetCurrTagValue("422"));//Refer,昨收
                  s.aPrice.data = dllReturnString(dllGetCurrTagValue("130"));//Open
                  s.aPrice.data = dllReturnString(dllGetCurrTagValue("131"));//High
                  s.aPrice.data = dllReturnString(dllGetCurrTagValue("132"));//Low
                  //s.aPrice.data = dllReturnString(dllGetCurrTagValue("121"));//Last/trade
                  s.Volume = Convert.ToInt64(dllReturnString(dllGetCurrTagValue("133")), 10);//Volume

                  //... 這裡可以設計載入日線資料 ....

                  // Copy the struct to unmanaged memory.
                  Marshal.StructureToPtr(s, PtrItem, false);
                }
            }
            else
            {
                ItemDatas s = (ItemDatas)Marshal.PtrToStructure(PtrItem, typeof(ItemDatas));//調出商品當前資料結構內容
                Int64 v = Convert.ToInt64(dllReturnString(dllGetCurrTagValue("133")), 10);//Volume
                if (v != s.Volume)
                {//有Tick
                  if (v > s.Volume)
                  {//確定總量是增加的才產生Tick, 否則視為修正而已
                        s.Last.price.data = dllReturnString(dllGetCurrTagValue("121"));//Last/trade
                        s.Last.qty = (Int32)(v - s.Volume);
                        Console.WriteLine("Tick " + s.Symbol.data + " V: " + v + " Last: " + s.Last.price.data + "(" + s.Last.qty + ")");
                  }
                  s.Volume = v;//update
                }
                //沒有要抓變化就不用比對直接一率更新即可
                s.aPrice.data = dllReturnString(dllGetCurrTagValue("422"));//Refer,昨收
                s.aPrice.data = dllReturnString(dllGetCurrTagValue("130"));//Open
                s.aPrice.data = dllReturnString(dllGetCurrTagValue("131"));//High
                s.aPrice.data = dllReturnString(dllGetCurrTagValue("132"));//Low
                //s.aPrice.data = dllReturnString(dllGetCurrTagValue("121"));//Last/trade

                //成交價和舊的最佳買賣價比較產生內外盤, 只是概念表達,可以轉成數值作更多的判斷
                if (s.Last.price.data == s.aBestBuy.price.data)
                {//成交在買價(內盤)
                }
                else if (s.Last.price.data == s.aBestSell.price.data)
                {//成交在賣價(外盤)
                }

                //... 五檔更新 ... 省略, 看完這邊的示範應該都會自己寫了

                //... 這裡可以設計KD資料處理 .... 例如當日KD最新狀態 假設當日的放在 array 0
                s.aKD_Day.Refer.data = s.aPrice.data;//昨收
                s.aKD_Day.Open.data = s.aPrice.data;//Open
                s.aKD_Day.High.data = s.aPrice.data;//High
                s.aKD_Day.Low.data = s.aPrice.data;//Low
                s.aKD_Day.Volume = s.Volume;//日總量

                // Copy the struct to unmanaged memory.
                Marshal.StructureToPtr(s, PtrItem, false);
            }

說明都在code中有提了,縮排對齊和顏料的部分就比較抱歉啦{:4_90:}

大概以下重點:

1. 指標的部分,IntPtr怎麼判斷null

2. 如何將填好資料的結構存放於API中的記憶體(dllCreateItemQuoteMemory)

3. 調出資料(dllGetItemQuoteMemory)怎麼由指標變成結構內容

4. 老孫上場大鬧洞房,行情資料什麼都有,愛怎麼玩自己玩

其他請自己領悟囉~

當然,上面的程式碼怎麼表現還是要看一下avi感受西夏婆熱情


內容中左邊是XP x86版程式
右邊是遠端Win7 x64版程式


就跟MMORPG的道理一樣,程式那麼大動畫那麼炫都是假的,

其實就只是一點點數據跑來跑去而已,

然後依據數據撥放動畫撥放特效,再弄個CD不能跳過來拖你的時間

浪費了青春與生命也只是資料庫的幾欄數據跟別人不一樣而已,

一堆脫機外掛或內掛跑的比你勤,還能直接拋數據作弊,

就連安裝作業系統,也要弄出個無人職守,那麼弄程式自動化也一樣,

都已經知道要作什麼了還看什麼介面,瞎泌線圖根本廢物,

其實當你在等成交當訊號,抓買賣作訊號的人早先跑一步了

當你以為預掛好委託可以優先成交時,你只是委託簿上面人家參考的訊號而已...{:4_163:}

所以訊號源真的超級重要的,策略和下單根本是其次

如果能放程式在券商後端收資料就好了{:4_115:}

這裡放個觀測點,看有沒有懶人要直接收cs檔


厲害的可以專案自建,要不然得先有上次的專案才好收喔!
還是有人純觀賞?!{:4_85:}


wujack 發表於 18-8-2 08:17

看了半天,沒有看到重點。直接貼到vs里,就可以執行嗎?

wujack 發表於 18-8-2 08:17

看了半天,沒有看到重點。直接貼到vs里,就可以執行嗎?

ram 發表於 18-8-7 09:38

wujack 發表於 18-8-2 08:17
看了半天,沒有看到重點。直接貼到vs里,就可以執行嗎?

怎麼這麼古椎咧///傑克

沒打碼的西夏婆裸在上面,行不行自己上了就知道啦!

然後都說很重要的要重複三遍

標題到內文已經五遍,現在再補一遍變成咑啵重要

當然是要有『上次』的付出,才能使用本次的招待阿

咯..咯...咯....{:4_162:}


wujack 發表於 18-8-7 12:25

難怪 我貼到vs里 都不能用…
頁: [1]
查看完整版本: 傑克請問上次那個QM只有2行是要怎麼用阿?!