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.
感谢论坛里两位高手,资深前辈的帮助,现在mt链接ib成功。 在个位数秒内连续成交三单,mt4与Ib误差在一个点以内,成交速度很快!不过,都是模拟帐户,不知道真实帐户如何,下次开发了稳健的程序,不知道有谁愿意来实验下?
这是学习最经典的例子! 当然还有国内一个高手的经典例子,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); }
加码:这是ea,放在expert中。演示的ea,是个日内高频刮头皮的系统,我测试了一天,在IB赚得一塌糊涂。当然,玩下而已。 或许到这里能基本解决你曾经的问题了。能在一个ea中完整的嵌入到ib的模块,再次对你的帮助表示感谢。
你将本机ip地址改为上面的地址,或者在上面代码里将// enable init below to show the tracewindow CONNECT("192.168.0.100",7496,1,-1);改为你现在本机的ip地址或改为127。0。0。1看看?
用这个IP地址就搞定了,成功的与tws搞上了关系。 mailema兄弟,试用了一下,还有几个问题,看看能否解决。 1)买、卖方向搞反了。 EA发出买的指令,复制到了tws那边变成卖了。 2)EA上挂的止盈,止损指令触发时,tws没有相应的复制。 3)目前只能用在EURUSD图上,其他图上无效。 4)可否将手动下单的指令也复制到tws去?
晕,方向搞反了啊,应该不会的,你再仔细看看IB中交易情况。这只是一个学习的实例,不能实现什么功能。可以别的啊,你在参数中把EUR改成比如GBP就可以了,这是ib的symbol。 总体解决方案:如果是脚本,类似mt2ib复制操作,好解决;这个我正在编写中,工程很大,脚本自身的缺点我还没完全弄明白。 如果只是ea,你说的那些问题止盈止损,我还没试验到哪里去,目前只试验到任何一个ea中随便市价确保成交某个单位到IB。但是理论上很容易,因为在mt4中看ib的行情都可以做到,止盈止损不过就是一个交互,或者简单点就是在mt4客户端的一个反向市价单再复制过去。 总体来说,一定得有好的稳健的策略才值得这样搞下去。这个不过是雕虫小技,但是很费些事,尤其是在稳健性上。 长远展望:我现在做了一些脚本,把功能分散,比如专门手工双击下单的(包含计算大小),一些ea完全自动交易。指标就直接在mt中看了
我原来以为把 ea的交易指令复制到tws是很简单的, 看了程序才明白要考虑的情况非常多。 如果做成象mt2ib那样,在script上面运行的方法是最简单的话,就用这个最简单的方法。 ea挂在script上面也可以运行的。 工作量蛮大的,辛苦兄弟了。
IB是股票,外汇,期权的复合,那些接口函数要同时满足三者,你说参数和情况能不复杂吗?mt只搞外汇,我才知道这绝对是做到极致的软件了。其他软件都无法"KISS"复杂是显然的。 那我们探讨下脚本有什么缺点?比如在极端情况下,断网,停电重启,无法成交等。 ea这些问题我都有解决办法。脚本还没想这么多。