Question
zydjohn on Wed, 18 Oct 2017 21:18:18
Hello:
I try to port some C# code into F#. Someone has shown the following C# code to subscribe a stock price data service. But the details are buried in a DLL file. The following is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using STOCKSDK;
using System.Runtime.InteropServices;
namespace test_md
{
class Program
{
static void on_tick( Tick tick)
{
System.Console.WriteLine(string.Format("{0} {1}.{2} {3}", tick.strtime, tick.exchange , tick.sec_id , tick.last_price));
}
static void on_bar(Bar bar)
{
System.Console.WriteLine(string.Format("{0} {1}.{2} {3}", bar.strtime, bar.exchange , bar.sec_id , bar.close));
}
static void Main(string[] args)
{
MdApi md = MdApi.Instance;
md.TickEvent += Program.on_tick;
md.BarEvent += Program.on_bar;
string v = md.Version();
string e = md.StrError(1004);
int ret = md.Init("UserID", "Password", MODE_PLAYBACK, "StockA.bar.daily", "2017-02-01 09:30:00", "2017-02-28 10:00:00");
if(ret != 0)
{
System.Console.WriteLine("Login Failed");
return;
}
md.Run();
System.Console.Read();
}
}
}
From object viewer for STOCKSDK, I can see public class MdApi has one property: public static STOCKSDK.MdApi Instance { get; }; this class has 5 different events:
public event STOCKSDK.MDBarCallback BarEvent Member of STOCKSDK.MdApi
public event STOCKSDK.MDErrorCallback ErrorEvent Member of STOCKSDK.MdApi
public event STOCKSDK.MDLoginCallback LoginEvent Member of STOCKSDK.MdApi
public event STOCKSDK.MDEventCallback MdEvent Member of STOCKSDK.MdApi
public event STOCKSDK.MDTickCallback TickEvent Member of STOCKSDK.MdApi
The Bar has the following definition in Object viewer: public Bar() Member of STOCKSDK.Bar
Bar has some members, like:
public string strtime Member of STOCKSDK.Bar
public string exchange Member of STOCKSDK.Bar
public string sec_id Member of STOCKSDK.Bar
public float close Member of STOCKSDK.Bar
The Tick has the following definition in Object viewer: public Tick() Member of STOCKSDK.Tick
Tick has some members, like:
public string strtime Member of STOCKSDK.Tick
public string exchange Member of STOCKSDK.Tick
public string sec_id Member of STOCKSDK.Tick
public float last_price Member of STOCKSDK.Tick
The Run method has the following signature: public int Run() Member of SOTCKSDK.MdApi
I understand the logical is like this: it first create an instance of MdApi, then subscribe to the Bar and Tick event, as long as the Bar and Tick event fires, call the event handler to print the necessary price information.
However, I can’t figure out how to rewrite the above C# code in F#, the following is my code:
#light
open STOCKSDK
open System
open System.Collections.Generic
open System.Linq
open System.Text
open System.Threading
open System.Runtime.InteropServices
let on_tick(tick: Tick) =
printfn "%s %s %s %1.2f" tick.strtime tick.exchange tick.sec_id tick.last_price
let on_bar(bar: Bar) =
printfn "%s %s %s %1.2f" bar.strtime bar.exchange bar.sec_id bar.close
[<EntryPoint>]
let main args =
let md = MdApi.Instance
md.add_TickEvent += on_tick
md.add_BarEvent += on_bar
let v = md.Version()
let e = md.StrError(1004)
let ret = md.Init("UserID", "Password", MODE_PLAYBACK, "StockA.bar.daily", "2017-02-01 09:30:00", "2017-02-28 10:00:00")
if (ret <> 0) then
printfn "Login failed!"
md.Run()
printfn "Done!"
0
The error messages are for the 2 lines:
md.add_TickEvent += on_tick
md.add_BarEvent += on_bar
Error FS0043 Expecting a type supporting the operator '+=' but given a function type. You may be missing an argument to a function.
In F#, when I typed md. I can see it has add_TickEvent; add_BarEvent; add_ErrorEvent; add_LoginEvent; add_MdEvent. But I have no idea how to rewrite the code in C# for this two lines:
md.TickEvent += Program.on_tick;
md.BarEvent += Program.on_bar;
Thanks for your advices.
Replies
Mr. Tines on Wed, 18 Oct 2017 22:49:38
The simplest translation of a C# event subscription like
md.TickEvent += Program.on_tick;
would be
md.TickEvent.AddHandler Program.on_tick
or you could also write
md.TickEvent |> Event.add Program.on_tick
zydjohn on Thu, 19 Oct 2017 07:45:45
Dear Mr. Tines:
Thank you very much for your reply. However, the SDK seems to be not F# friendly. I am using Visual Studio 2017.
If I create a C# project, then in IDE, when I typed md.
Then I can see all events. Look at the picture.
But if I create a F# project, then in IDE, when I typed md.
Then I can only see the add_XXXevent; see the picture again; there is no such events available as in C#.
Therefore, it is impossible to use the codes you provided.
Their SDK support 5 programming languages: C/C++; C#; Matlab; Python; GNU R. Unfortunately, F# is not supported.
If interested, you can download their SDK from this web site: http://www.myquant.cn/downloads/
The web site has some Chinese explanations, just ignore them, to download C# SDK, you can simply click on the Windows Icon besides the C# language (语言)。
Unzip the downloaded file, there are 4 C# examples, in C# everything looks well. But when I tried to use the SDK in F#, the events functions really did NOT work; but the other functions seem to be working in F#, as long as they don’t need event functions. But the event functions are the most important functions in the SDK, since all the stock price subscriptions need the events to work.
Thanks again for your help.
Have a nice day!
Mr. Tines on Thu, 19 Oct 2017 15:18:23
Prompted by this hover-text message
this is what ended up building for me
open GMSDK let on_tick(tick: Tick) = printfn "%s %s %s %1.2f" tick.strtime tick.exchange tick.sec_id tick.last_price let on_bar(bar: Bar) = printfn "%s %s %s %1.2f" bar.strtime bar.exchange bar.sec_id bar.close [<EntryPoint>] let main args = let md = MdApi.Instance md.add_TickEvent (fun x -> on_tick x) md.add_BarEvent (fun x -> on_bar x) let v = md.Version() let e = md.StrError(1004) let ret = md.Init("UserID", "Password", MDMode.MD_MODE_PLAYBACK, "StockA.bar.daily", "2017-02-01 09:30:00", "2017-02-28 10:00:00") if (ret <> 0) then printfn "Login failed!" md.Run() |> ignore printfn "Done!" 0
It needs to be a lambda so it gets automatically converted to a delegate type, even if usually this sort of lambda would want to be refactored to a direct function call.
zydjohn on Thu, 19 Oct 2017 19:45:49
Dear Mr. Tines:
Thank you very much for your code, your code get compiled, but when running, there was no results. Even the C# code did NOT generate any results. It could mean something wrong with their stock server. I asked the technical support, hope they can help me to debug the C# code, if C# code works, I think F# code should also work.
Thanks and have a nice day!
zydjohn on Fri, 20 Oct 2017 09:12:06
Dear Mr. Tines:
Thanks, the technical support fixed the issue, it works now.
However, I can't see the hover-text message which you showed here.
In VS 2017, when I hover the md., I can only see:
MdApi.add_BarEvent(value: MDBarCallback): unit
Let me know how you can find the other information.
Thanks and have a nice day!
John
Mr. Tines on Sat, 21 Oct 2017 15:41:19
I was using VS2017 15.4.1, and I got that message when I'd put in the original code from your first post
md.TickEvent += Program.on_tick; md.BarEvent += Program.on_bar;
and got a red squiggly underline. I worked through to
md.add_TickEvent (fun x -> on_tick x) md.add_BarEvent (fun x -> on_bar x)
which compiled, and then to take the picture, just backed off to
md.TickEvent (fun x -> on_tick x) md.add_BarEvent (fun x -> on_bar x)to get back to a state where I could get the interesting message.
zydjohn on Mon, 06 Nov 2017 09:17:35
Thank you very much for your advice.
However, when I used VS2017 15.4; the debug function seems gone, I can't run any program in debug mode; so I went back to VS2017 15.3.
Hope I can go to next version of VS2017 where I can run program in debug mode.
I will try to figure out your way to find the solution.
Thanks again!