MT4到IB的通道

Discussion in 'MetaTrader' started by mailema, Aug 19, 2008.

  1. every thing is down.if someone want to know,pls contract me or just like wj2000's words.read the helpfile.

    Later i will post some example to show how to get it.
     
    Last edited by a moderator: Sep 1, 2008
  2. 感谢论坛里两位高手,资深前辈的帮助,现在mt链接ib成功。

    在个位数秒内连续成交三单,mt4与Ib误差在一个点以内,成交速度很快!不过,都是模拟帐户,不知道真实帐户如何,下次开发了稳健的程序,不知道有谁愿意来实验下?
     
    Last edited by a moderator: Oct 26, 2008
  3. 有必要吗?是IB你用着熟吧
     
  4. 有不少mt的fans想在ib做自动交易吧,反正闲着也是闲着,动动手也好。
     
  5. MT的交易代码我觉得不比ib差
     
  6. 看twslink说明和实例就可以了,然后在MT4里做个2次“封装”函数或脚本。
    不过IB的东西比较怪,只提供了TWS的API,所有的东西还是需要启动tws才能使用,太不方便和高效了。
     
  7. 这是学习最经典的例子!

    当然还有国内一个高手的经典例子,mt2ib,潘教授的作品,相当厉害(好象有不少错误处理没捕获),还在全面学习中。估计不久,有一个更厉害更完善的mt2ib的脚本出现。
    我把包含文件一起发上来,至于twslink.dll ,请大家自己下载,放在library目录中。

    #include <WinUser32.mqh>

    //+------------------------------------------------------------------+
    //| DLL imports |
    //+------------------------------------------------------------------+
    #property copyright "Copyright ?2007, www.Trade-Commander.org"
    #property link "http://www.Trade-Commander.org"
    #import "twslink.dll"
    int REGISTER_CONTRACT(string symbol,string sectype,string currency,string exchange,string primaryExchange,string expiry,string right,double strike,string multiplier,int expired,double mintick);
    int REGISTER_CONTRACT_XML(string pathandfile,int overwrite_load_flag);
    int REGISTER_CONTRACT_XML_STYLE(string pathandfile);
    string GET_CONTRACTUID_LIST(string symbol,string sectype,string currency,string exchange,string primaryExchange,string expiry,string right,double strike,string multiplier,string delimiter);
    int WAIT_FOR_ACCEPTED(int uicontract,int timeoutmilliseconds);
    int ADD_COMBO_LEG(int uicontract,int conid,int ratio,int openClose,string action,string exchange,int shortsaleslot,string designatedlocation);
    int REM_COMBO_LEG(int uicontract,int conid,int ratio,int openClose,string action,string exchange,int shortsaleslot,string designatedlocation);
    int REQ_MARKET_DATA(int contractuid,int subscribe,string generictick,int snapshot_flag);
    int REQ_BAR_DATA(int contractuid,int subscribe,int barsize,int whatotshow,int rthonly_flag);
    double GET_MARKET_DATA(int contractuid,int type,int subtype,int latest_flag);
    double GET_BAR_DATA(int contractuid,int type,int valueid,int size,int idx);
    string QUERY_MARKET_DATA(int contractuid,string descriptor);
    int GET_TICK(int contractuid,int timeout);
    int WAIT_FOR_TICK(int uidfilter,int tickfilter,int timeout);
    double EXTRACT_MARKET_DATA(int idx,string quotestream);
    double VALIDATE_PRICE(int contractid,double Price,int ceil_flag);
    string EXTRACT_ARRAY_VALUE(int idx,string quotestream,string delim);
    int WAIT_FOR_REQ_PROCESSED(int timeoutmilliseconds);
    int REQ_ACC_UPDATE(string accname,int subscribe,int timeoutmilliseconds);
    int WAITDLL(int timeoutmilliseconds);
    int WAIT_FOR_EVENT(int evfilter,int subfilter,int timeout,int reset_event_flag);
    string GET_EVENT_VAL(int uid,int valueid);
    int START_APPLICATION(string commandline,string startupdir,int timeout);
    int GET_CONTRACT_STATUS(int uidcontract);
    int PLACE_ORDER(int contractid,int uidorder,string action,string ordertype,int totalquantitiy,double limitprice,double auxprice,string tif,int transmit,int uidparentorder,string GTD,string GAT,int overwritetimeoutmints);
    int BUY_LMT(int contractid,int uidorder,double limitprice,int Size,string tif,int transmit);
    int SELL_LMT(int contractid,int uidorder,double limitprice,int Size,string tif,int transmit);
    int BUY_MKT(int contractid,int Size,int transmit);
    int SELL_MKT(int contractid,int Size,int transmit);
    int BUY_STPLMT(int contractid,int uidorder,double lmtprice,double stopprice,int Size,string tif,int transmit);
    int SELL_STPLMT(int contractid,int uidorder,double lmtprice,double stopprice,int Size,string tif,int transmit);
    int BUY_STP(int contractid,int uidorder,double stopprice,int Size,string tif,int transmit);
    int SELL_STP(int contractid,int uidorder,double stopprice,int Size,string tif,int transmit);
    int BUY_TRAIL(int contractid,int uidorder,double abstrailamt,int Size,string tif,int transmit);
    int SELL_TRAIL(int contractid,int uidorder,double abstrailamt,int Size,string tif,int transmit);
    int TOGGLE_ORDER(int contractid,int uidorder,int lmtpips,int stppips,int newSize,int transmit);
    int TOGGLE_ORDER_PCT(int contractid,int uidorder,double absolute_percentage_change,double stppct,int newSize,int transmit);
    int SET_ORDERVAL(int uidorder,int valueid,string val,int transmit);
    string GET_ORDER_VAL(int uidorder,int valueid,string extraparam);
    string GET_ORDERUID_LIST(int contractid,string action,string type,int status,int isdead,double lowerprice,double upperprice,string exchange,string orderref);
    string GET_OPEN_ORDERUID_LIST(int contractid,string action,string type,double priceabove,double pricebelow);
    double GET_EXECUTION_PRICE(int uidorder,int type,int idx);
    int CONVERT_ID(int sourceid,int conversiontype);
    string CONVERT_ID_STRING(string sourcestring,int conversiontype);
    int SET_FA_MEMBERS(int uidorder,string account,string faGroup,string faProfile,string faMethod,string faPercentage,int transmit);
    int WAIT_FOR_ORDER_STATUS(int uidorder,int statusid,int timeoutmilliseconds,int statusidbreak);
    int WAIT_FOR_FILLED(int uidorder,int timeoutmilliseconds);
    int WAIT_FOR_SUBMITTED(int uidorder,int timeoutmilliseconds,int sub_stat_only);
    int WAIT_FOR_ORDER_STATUS_RNG(int uidorder,int lowerstatusid,int upperstatusid,int timeoutmilliseconds,int statusidbreak);
    int GET_ORDER_STATUS(int uidorder);
    int GET_ORDER_ERROR(int uidorder);
    int ORDER_MODIFIABLE(int uidorder);
    string GET_ACC_VAL(int idaccval,string currency,string accountlist,int valtype);
    double GET_MARKET_VAL(string currency,int idaccval,string accounts);
    double GET_PORTFOLIO_VAL(int uid,int idaccval,string accounts);
    string GET_CONTRACT_VAL(int contractid,int idaccval,string param,string accounts);
    int SET_CONTRACT_VAL(int uid,int idvalue,string pValue);
    string GET_BASECURRENCY(string accname);
    double GET_CASH_BALANCE(string currency,string accname);
    double GET_EXCHANGE_RATE(string currency1,string currency2);
    string GET_ACC_NAME(int index);
    int GET_POSITIONS(int contractid,string accname);
    int ATTACH(int uidchildorder,int uidparentorder);
    int TRANSMIT(int uidorder,int uidcontract,string otypefilter);
    int CANCEL_ORDER(int uidorder,int contractid,string otypefilter,int pending,string side);
    double GET_STOPPROTECTION(int uidcontract,int respectstoplimit);
    int CLOSE_CONTRACT(int contractid,double price,string account,string typefilter);
    int CLOSE_CASH_POSITION(string currency,double price,string account);
    int FORCE_CONTRACT(int contractid,double newSize,int isRelative,double price,string account,string typefilter);
    int SET_INDICATOR_SIZE(int contractid,int indiid,int size);
    int INITDLL(int timeoutminutes,string socklog,int flags,int TWSLogLevel,int DLLLogLevel,int reconnectiontime_ms);
    int CONNECT_XML(int xmlid,int timeout);
    int INITDLL_XML(string filename);
    int CONNECT(string sHost,int iport,int startingClientID,int timeout);
    int DISCONNECT();
    int SET_DLLPARAM(string sParam,string sVal);
    int SET_STOP(int flag);
    int SET_BREAK(int flag);
    int DISPOSE();
    string GET_DLLSTATUS(string sParam,int lParam);
    int GET_CONNECTED();
    int CUSTOMCOMMENT(string sComment,int loglevel);
    int SEND_MAIL(string originator,string recipients,string subject,string text,string smtpserver);
    int TO_FILE(string sFileName,string sText,int write_mode);
    string FROM_FILE(string sFileName,int remove_control_char_flag);
    int GET_LNG_VAR(string Name);
    double GET_DBL_VAR(string Name);
    string GET_STR_VAR(string Name);
    int SET_LNG_VAR(string Name,int val);
    int SET_DBL_VAR(string Name,double val);
    int SET_STR_VAR(string Name,string val);
    int REM_LNG_VAR(string Name);
    int REM_DBL_VAR(string Name);
    int REM_STR_VAR(string Name);
    int SET_EVENT_HANDLER(int callback_handle,int subscription_mask,int traget_thread_id);
    int SET_EVENT_HANDLER_OLE(int callback_handle,int subscription_mask,int traget_thread_id);
    #import

    extern int TriggerPips = 5;
    extern int DefaultOrderSize = 100000;
    /// symbol information
    extern string Sym = "EUR";
    extern string Currency = "USD";
    extern string Exchange = "IDEALPRO";
    extern string PrimExchange = "";
    extern string Type = "CASH"; // CASH,STK,FUT,OPT,FOP
    extern string Expiry = ""; // format: yyyyymm FUT,OPT,FOP only
    extern string Right = ""; // CALL or PUT OPT,FOP only
    extern double Strike = 0.0;
    extern double DailyNetLiquidStop = 2000; // risk at the most of 2000 BASE as negative NetLiquidation DrawDown
    extern double DailyNetLiquidTarget = 0; // target net liquidation gain. default 'let run'.


    int symboluid = 0; // dll internal unique id for contract
    double LastEntry = 0.0;
    int CurrentPositions = 0;
    int OrderSize = 0;
    string accountname = "888"; // should be relevant in advisor context only
    int contract_accepted = 0;
    double MinTick = 0.0;
    double PipDiff = 0.0;
    int oid = 0; // uid of last oder
    string StringValBuffer = ""; // buffers string return value
    string BaseCurrency = "";
    string twslinkpath = "#log\twslinkmt4.log";
    ///
    /// parameter to implement a minum risk
    ///
    double CurrentNetLiq = 0.0; // current netliquitation
    double InitialNetLiq = 0.0; // daily initial netliquitation
    bool allowTrades = true;

    int init()
    {

    // init with execution report and open orders
    INITDLL(-1,twslinkpath,0,3,3,10000);
    // enable init below to show the tracewindow
    CONNECT("192.168.0.100",7496,1,-1);
    //-1表示无限等待
    symboluid = REGISTER_CONTRACT(Sym,Type,Currency,Exchange,PrimExchange,Expiry,Right,Strike,"",0,0.0);
    ValidateContract();
    return(1);
    }

    bool ValidateContract()
    {
    if(symboluid > 0)
    {
    // contract not yet accepted by TWS
    if(contract_accepted < 1)
    {
    // wait at the most of 1 second until accetped
    contract_accepted = WAIT_FOR_ACCEPTED(symboluid,1000);
    // < -1: error, -1: timeout due to currently not connected, 0: timeout (tws may busy currently)
    if(contract_accepted < -1)
    {
    MessageBox("Contract "+Sym+","+Type+","+Currency+","+Exchange+" has not been accepted.",
    " Check Contract Specification and check again",MB_OK|MB_ICONQUESTION);
    return (false);
    }
    // once accepted, get mintick and base currency
    else if(contract_accepted >= 1)
    {
    // get the mintick
    StringValBuffer = GET_CONTRACT_VAL(symboluid,20,"",accountname);
    //没有accountname也可以
    if(StringValBuffer == "nok" || StringValBuffer == "cnd")
    {
    Print("could not get mintick");
    }
    else
    {
    MinTick = StrToDouble(StringValBuffer);
    Print("mintick="+StringValBuffer);
    }
    // get the base currency
    BaseCurrency = GET_BASECURRENCY(accountname);
    Print("contract accepted");
    }
    }
    return (true);
    }
    else
    {
    // this should never happen
    MessageBox("Contract Registration failed. Check logfile for more Information",MB_OK|MB_ICONQUESTION);
    return (false);
    }
    }

    int start()
    {

    // do this every event. once accepted this costs nearly no cpu load
    if(ValidateContract() == false)
    return;

    // update current positions (if not connected, the last known value is returned).
    CurrentPositions = GET_POSITIONS(symboluid,accountname);

    /*Comma separated List of Accounts or empty. In Case of FA Account
    the Sum of Positions is returned. An empty Account String than returns
    the Sum of Contract Positions over all Accounts.*/

    Print("CurrentPositions=",CurrentPositions);//看头寸是多大?

    // get the current net liquidation value净额清算
    StringValBuffer = GET_ACC_VAL(12,"",accountname,0);//12 NetLiquidation,

    if(StringValBuffer != "nok")
    {CurrentNetLiq = StrToDouble(StringValBuffer);
    Print("CurrentNetLiq=",CurrentNetLiq);}
    // save the inital value for delta calculation (need for risk)
    if(InitialNetLiq == 0)
    InitialNetLiq = CurrentNetLiq;

    // check risk or target
    if((CurrentNetLiq-InitialNetLiq) < -DailyNetLiquidStop)
    {
    allowTrades = false;
    Print("Net Liquidation Stop reached.");
    }
    else if(DailyNetLiquidTarget > 0 && (CurrentNetLiq-InitialNetLiq) > DailyNetLiquidTarget)
    {
    allowTrades = false;
    Print("Net Liquidation Target reached. Profit = " + (CurrentNetLiq-InitialNetLiq) + " " + BaseCurrency);
    }
    // at one o'clock reset risk settings (disable these lines if risk should be total rather than daily)
    if(Hour() == 1)
    {
    allowTrades = true;
    InitialNetLiq = CurrentNetLiq;
    }
    if(LastEntry == 0.0)
    LastEntry = Ask;
    // calculate move in pips since last entry
    if(MinTick > 0.0 && allowTrades == true)
    {
    PipDiff = (LastEntry - Ask) / MinTick;
    Print("PipDiff = "+PipDiff);
    /// since last entry market moved n pips up -> go short
    if(PipDiff >= TriggerPips)
    {
    OrderSize = CurrentPositions + DefaultOrderSize;
    // be sure ordersize is real accepted by tws. otherwise order gets rejected.
    // further api version may provide the minumum ordersize.
    if(OrderSize > 0 && OrderSize <= DefaultOrderSize) // limit maximum positions to DefaultOrderSize
    {
    // place market order
    oid = SELL_MKT(symboluid,OrderSize,1);
    if(oid <= 0)
    Print("SELL market failed");
    else
    {
    Print("SELL market " + OrderSize + " near " + Bid);
    LastEntry = Bid;
    }
    }
    }
    /// since last entry market moved n pips down -> go long
    else if(PipDiff <= -TriggerPips)
    {
    OrderSize = CurrentPositions + DefaultOrderSize;
    // be sure ordersize is real accepted by tws. otherwise order gets rejected.
    // further api version may provide the minumum ordersize.
    if(OrderSize > 0 && OrderSize <= DefaultOrderSize) // limit maximum positions to DefaultOrderSize
    {
    // place market order
    oid = BUY_MKT(symboluid,OrderSize,1);
    if(oid <= 0)
    Print("BUY market failed");
    else
    {
    Print("BUY market " + OrderSize + " near " + Ask);
    LastEntry = Ask;
    }
    }
    }
    }

    return (1);
    }
     
    Last edited by a moderator: Sep 3, 2008
  8. 这个文件是放在那个目录下面?

    script? or indicator? or expert?
     
  9. 加码:这是ea,放在expert中。演示的ea,是个日内高频刮头皮的系统,我测试了一天,在IB赚得一塌糊涂。当然,玩下而已。:D

    或许到这里能基本解决你曾经的问题了。能在一个ea中完整的嵌入到ib的模块,再次对你的帮助表示感谢。
     
  10. twslink 与 tws 连接不上,是否是因为IP地址不对? 我是用路由器上网的。
     
  11. 你将本机ip地址改为上面的地址,或者在上面代码里将// enable init below to show the tracewindow
    CONNECT("192.168.0.100",7496,1,-1);改为你现在本机的ip地址或改为127。0。0。1看看?
     
  12. 对,晕,我又泄漏了我的本机地址,哈哈。192.168.0.100是我的计算机的。你改成你自己现在用的,一般是192.168 开头的,如果你用路由的话。
     
  13. 可能改成127.0.0.1本机地址通用性最好?!
     
  14. 用这个IP地址就搞定了,成功的与tws搞上了关系。


    mailema兄弟,试用了一下,还有几个问题,看看能否解决。
    1)买、卖方向搞反了。 EA发出买的指令,复制到了tws那边变成卖了。
    2)EA上挂的止盈,止损指令触发时,tws没有相应的复制。
    3)目前只能用在EURUSD图上,其他图上无效。
    4)可否将手动下单的指令也复制到tws去?
     
  15. 晕,方向搞反了啊,应该不会的,你再仔细看看IB中交易情况。这只是一个学习的实例,不能实现什么功能。可以别的啊,你在参数中把EUR改成比如GBP就可以了,这是ib的symbol。

    总体解决方案:如果是脚本,类似mt2ib复制操作,好解决;这个我正在编写中,工程很大,脚本自身的缺点我还没完全弄明白。

    如果只是ea,你说的那些问题止盈止损,我还没试验到哪里去,目前只试验到任何一个ea中随便市价确保成交某个单位到IB。但是理论上很容易,因为在mt4中看ib的行情都可以做到,止盈止损不过就是一个交互,或者简单点就是在mt4客户端的一个反向市价单再复制过去。

    总体来说,一定得有好的稳健的策略才值得这样搞下去。这个不过是雕虫小技,但是很费些事,尤其是在稳健性上。

    长远展望:我现在做了一些脚本,把功能分散,比如专门手工双击下单的(包含计算大小),一些ea完全自动交易。指标就直接在mt中看了
     
  16. 我原来以为把 ea的交易指令复制到tws是很简单的,
    看了程序才明白要考虑的情况非常多。

    如果做成象mt2ib那样,在script上面运行的方法是最简单的话,就用这个最简单的方法。
    ea挂在script上面也可以运行的。

    工作量蛮大的,辛苦兄弟了。
     
  17. IB是股票,外汇,期权的复合,那些接口函数要同时满足三者,你说参数和情况能不复杂吗?mt只搞外汇,我才知道这绝对是做到极致的软件了。其他软件都无法"KISS"复杂是显然的。

    那我们探讨下脚本有什么缺点?比如在极端情况下,断网,停电重启,无法成交等。

    ea这些问题我都有解决办法。脚本还没想这么多。
     
  18. 个人认为一个比较好的方法是将twslink的函数先封装成接独立的mt4里一些有特定作用的函数(比如市价委托,限价委托等),然后在mt4里使用就方便了。
     
  19. 对,应该如此。
     
  20. 晕,你们都已经实现了啊!?
    是可以免费共享,还是要出售的啊?贵不贵啊?