2015-02-08 150 views
-2

我在Excel中有RTD服務器,它從thinkorswim應用程序中提取數據。我想將數據轉移到C#中。我的編程經驗有限,因此閱讀了C#中有關RTD服務器實現的多個教程,但其中大多數對我來說都是先進的。所以我想知道是否有人可以提供一些入門閱讀材料。下面是我想實現的示例代碼:C#中的RTD服務器 - 從哪裏開始

http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/

我複製並粘貼它到Visual Studio(VS)和被稱爲類RtdClient.cs。 VS立即突出顯示以下行:

ComImport, TypeLibType((short)0x1040) 
MarshalAs 
MethodImpl 

並寫了無法找到的類型和命名空間。

我是否缺少任何參考? 我添加了COM類型Tos.RTD的參考,但它沒有幫助。

此外在註冊表中我發現與Tos.RTD和CLSID文件夾。我假設CSLID指向COM類型?

在VS Tos.RTD有幾個接口。在上面的鏈接中,我沒有看到這些接口的實現方法。哪裏不對?

我也看過以下RTD through reflection我知道第二個鏈接依賴於反思。這兩種方法的優點/缺點是什麼?哪一個在概念上更有意義?

正如你看起來我迷路了,所以任何建議將不勝感激。

回答

2

一個RTD服務器是明確的Excel,並不會幫助你在C#中。你可以反編譯它,我想看看它是如何從ThinkOrSwim獲取數據的,但是我會想象他們有一個你可以使用的API,如果你更多地看一看。

+0

謝謝凱利!我如何反編譯它?我看着任務管理器和服務,並沒有找到任何相關的項目。我想象Tos.RTD在Excel過程中運行。我需要反編譯Excel過程嗎?除了ThinkOrSwim,TD Ameritrade還提供獨立的API,但他們想要錢,而ThinkOrSwim是免費的。 – user1700890 2015-02-08 13:55:39

+0

RTD服務器只是您計算機上的DLL。你將需要找到那個然後使用像反射器。 – Kelly 2015-02-09 16:01:32

3
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Threading; 
using System.Runtime.InteropServices; 
using System.Runtime.CompilerServices; 


namespace MyRTD 
{ 
    class Program 
    { 
    static void Main(string[] args) 
     { 
     //Based off of http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/ 
     //and http://stackoverflow.com/questions/26726430/r6025-pure-virtual-function-call 


      //var tosClassId = new Guid(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Tos.RTD\CLSID", "", null).ToString()); 
      var tosClassId=new Guid("{1B415BA9-E543-41BD-8EB1-CB12A5B7678F}"); 
      var rtdClient = new RtdClient(tosClassId); 

      var date = DateTime.Now.Date; 

      List<string> tos_sym = new List<string>(); 
      tos_sym.Add(".AAPL160819C106"); 
      tos_sym.Add(".AAPL160819C107"); 
      tos_sym.Add(".AAPL160819C108"); 
      tos_sym.Add(".AAPL160819C109"); 

      foreach (var optSym in tos_sym) 
       { 
       var optBid = GetDouble(rtdClient, optSym, "BID"); 
       var optAsk = GetDouble(rtdClient, optSym, "ASK"); 
       var optDelt = GetDouble(rtdClient, optSym, "DELTA"); 

       Console.WriteLine(optSym + " BID: " + optBid + " ASK: " + optAsk + " DELTA: " + optDelt); 

       } 
      } 

      static double GetDouble(IRtdClient client, string symbol, string topic) { 
       object value; 
       if (client.GetValue2(TimeSpan.FromSeconds(3), out value, topic, symbol)) { 
        try { return double.Parse(value.ToString()); } catch { return 0; } 
       } 
       return 0; 
      } 

     public interface IRtdClient 
     { 

      bool GetValue2(TimeSpan timeout, out object value, params object[] args); 
     } 

     public class RtdClient : IRtdClient 
     { 

      readonly Guid ServerId; 
      static readonly Dictionary<Guid, IRtdServer> servers = new Dictionary<Guid, IRtdServer>(); 
      static readonly Dictionary<Guid, int> topicIds = new Dictionary<Guid, int>(); 

      public RtdClient(Guid serverId) 
      { 
       ServerId = serverId; 
      } 

      public bool GetValue2(TimeSpan timeout, out object value, params object[] args) 
      { 

       value = null; 
       var server = GetRtdServer(); 
       var topicId = GetTopicId(); 

       var sw = Stopwatch.StartNew(); 
       var delay = 200; 

       try 
       { 
        server.ConnectData(topicId, args, true); 
        while (sw.Elapsed < timeout) 
        { 
         Thread.Sleep(delay); 
         delay *= 2; 
         var alive = server.Heartbeat(); 
         if (alive != 1) 
         { 
          // TODO: What should be done here? 
          return false; 
         } 
         var refresh = server.RefreshData(1); 
         if (refresh.Length > 0) 
         { 
          if (refresh[0, 0].ToString() == topicId.ToString()) 
          { 
           value = refresh[1, 0]; 
           return true; 
          } 
         } 
        } 
       } 
       catch (Exception ex) 
       { 
        // TODO: Log exception 
        return false; 
       } 
       finally 
       { 
        server.DisconnectData(topicId); 
        sw.Stop(); 
       } 
       return false; 
      } 


      IRtdServer GetRtdServer() 
      { 
       IRtdServer server; 
       if (!servers.TryGetValue(ServerId, out server)) 
       { 
        Type rtd = Type.GetTypeFromCLSID(ServerId); 
        server = (IRtdServer)Activator.CreateInstance(rtd); 
        servers[ServerId] = server; 
       } 
       return server; 
      } 

      int GetTopicId() 
      { 
       int topicId = 0; 
       if (topicIds.TryGetValue(ServerId, out topicId)) 
       { 
        topicId++; 
       } 
       topicIds[ServerId] = topicId; 
       return topicId; 
      } 
     } 
     [ComImport, TypeLibType((short)0x1040), Guid("EC0E6191-DB51-11D3-8F3E-00C04F3651B8")] 
     public interface IRtdServer 
     { 
      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10)] 
      int ServerStart([In, MarshalAs(UnmanagedType.Interface)] IRTDUpdateEvent callback); 

      [return: MarshalAs(UnmanagedType.Struct)] 
      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] 
      object ConnectData([In] int topicId, [In, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref object[] parameters, [In, Out] ref bool newValue); 

      [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] 
      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)] 
      object[,] RefreshData([In, Out] ref int topicCount); 

      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(13)] 
      void DisconnectData([In] int topicId); 

      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(14)] 
      int Heartbeat(); 

      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(15)] 
      void ServerTerminate(); 
     } 

     [ComImport, TypeLibType((short)0x1040), Guid("A43788C1-D91B-11D3-8F39-00C04F3651B8")] 
     public interface IRTDUpdateEvent 
     { 
      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10), PreserveSig] 
      void UpdateNotify(); 

      [DispId(11)] 
      int HeartbeatInterval 
      { 
       [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] 
       get; 
       [param: In] 
       [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] 
       set; 
      } 

      [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)] 
      void Disconnect(); 

     } 


    } 
} 
+0

這起作用。作爲原創作者評論,有許多符號不穩定。我仍然在搞這個。這應該讓你感動。 – Silvo 2016-07-20 17:37:33

+0

有趣的是,我會學習。 – user1700890 2016-07-20 18:50:24