个人学识有限,分享给大家研究。 有点神奇,第一次测试时会自主训练,形成一个TXT文件,记录学习的过程。这时候再进行测试的话,胜率就高得离谱了,这个TXT文件在tester/files文件下面,当然,也可以放在experts\files目录中,进行foreward测试。 以下是两个博客地址, http://www.earnforex.com/blog/2008/08/statstical-forex-system-example-mt4-expert-advisor/ http://www.earnforex.com/blog/2010/04/self-learning-forex-expert-advisor/ Code: //+------------------------------------------------------------------+ //| Rich.mq4 | //| ?2008, Christopher | //| http://www.expert-profit.webs.com/ | //+------------------------------------------------------------------+ // // This EA uses MapPath file ("rl.txt" by default) from your // /tester/files/ (for strategy tester) or /experts/files/ (for actual use) // to get the initial statistics. It also continues to gather its own // statistics and appends it to the initial file, saving it after // deinitilizing. // // Modified by Robert Hill // Aug 20, 2010 // // 1. Choose 4 or 5 decimal brokers, (it only works on 4 decimals now, // and it seems like everyone is going to 5 digits. // Done using myPoint to replace Point // 2. Keep the aggressive setting, but also enable the user to have a // conservative setting as well. Enable it to work with 1:100 and 1:200 brokers. // MOST brokers that allow the higher leverages, on larger accounts, limit the leverage to 1:200. // 3. Have an entry where you can tell it the maximum amount of lots to trade. // In other words, once it grows the account to where it's trading with 100 lots // (in the case of Forexlite) or 20 lots, (in the case of GoMarkets), // then it would continue to trade at that maximum level // // This change was also made by John Taylor and his money management code is used // Done #property copyright "?2010, Christopher" #property link "http://www.expert-profit.webs.com/" #include <stdlib.mqh> #define BUY_MAP 1 #define SELL_MAP 0 #define HOLD_MAP 2 //Map size for BUY and SELL #define MAPBASE 10000 //Map size for HOLD #define HOLDBASE 25000 //Number of map memory-cells for each bar #define VBASE 7 int LastBars = 0; double vector[VBASE]; //Vector with memory-cells for current bar double vectorp[VBASE]; //Vector with memory-cells for previous bar //3 Maps double MapBuy[MAPBASE][VBASE]; double MapSell[MAPBASE][VBASE]; double MapHold[HOLDBASE][VBASE]; //Min and Max amounts of pips of profit to consider teaching BUY and SELL maps extern int MinPips = 5; extern int MaxPips = 43; extern int TakeProfit = 150; extern int StopLoss = 100; //20100820 JT - Set Lots to 0 to use sqrt of AccountBalance extern string mm = "Set Lots to 0 to use sqrt of AccountBalance"; extern double Lots = 0.01; //20100820 JT - Changed to be less aggressive default extern double MaxLots=3; //20100820 JT - Changed to be less aggressive maximum extern string mm1 = "Adjust this to be more conservative or aggressive"; extern double Lots_Per_10K = 1.0; extern double Slippage = 3; extern string MapPath = "rl.txt"; extern string EAName = "RowLearner"; string myMapPath; int Magic; double TLots; // Item 1 double myPoint; //20100820 JT - Pseudo-constants static double C_MinLots; // Min qty that can be traded static double C_MaxLots; // Max qty that can be traded static double C_LotValue; // Value of 1 lot in base currency static double C_LotStep; // Min lot increment static int C_LotStepDigits; // Dec. places of lot step static double C_StopLevelVal; // e.g. 0.0002 static double C_Point; // Size of minimum price move // End add pseudo-constants //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { Magic = Period()+1937004; myMapPath = Symbol() + "_" + MapPath; // Robert added Item 1 - replace Point with myPoint myPoint = GetPoint(Symbol()); InitKohonenMap(); LoadKohonenMap(); TLots = Lots; return(0); //20100820 JT - Cache MarketInfo C_MinLots = MarketInfo(Symbol(),MODE_MINLOT); C_MaxLots = MarketInfo(Symbol(),MODE_MAXLOT); C_LotValue = MarketInfo(Symbol(),MODE_LOTSIZE); C_LotStep = MarketInfo(Symbol(),MODE_LOTSTEP); C_Point = MarketInfo(Symbol(),MODE_POINT); double lotStep = C_LotStep; while (lotStep < 1) { lotStep = lotStep * 10; C_LotStepDigits += 1; } C_StopLevelVal = MarketInfo(Symbol(),MODE_STOPLEVEL)*Point; // End cache MarketInfo //20100820 JT - Adjust params (crudely) for different point sizes if (C_Point==0.00001 || C_Point==0.001) { // Handled by Robert's use of myPoint // MinPips*=10; // MaxPips*=10; // TakeProfit*=10; // StopLoss*=10; Slippage*=3; } // End point size adjustment } //+------------------------------------------------------------------+ //| main expert function | //+------------------------------------------------------------------+ int start() { if (Bars < 7) return(0); //Wait for the new Bar in a chart. if (LastBars == Bars) return(0); else LastBars = Bars; CloseAllOrders(); double bmu[3] = {0, 0, 0}; //Calculating the Tom Demark's pivot points over last 5 bars double hi[5] = {0,0,0,0,0}; double lo[5] = {0,0,0,0,0}; hi[0] = High[2]; hi[1] = High[3]; hi[2] = High[4]; hi[3] = High[5]; hi[4] = High[6]; lo[0] = Low[2]; lo[1] = Low[3]; lo[2] = Low[4]; lo[3] = Low[5]; lo[4] = Low[6]; double H = hi[ArrayMaximum(hi)]; double L = lo[ArrayMinimum(lo)]; vectorp[0] = (H + L + Close[2]) / 3; //The difference between pivots and Open price is used to normalize statistics vectorp[1] = (2 * vectorp[0] - L) - Open[1]; vectorp[2] = (vectorp[0] + H - L) - Open[1]; vectorp[3] = (H + 2 * (vectorp[0] - L)) - Open[1]; vectorp[4] = (2 * vectorp[0] - H) - Open[1]; vectorp[5] = (vectorp[0] - H + L) - Open[1]; vectorp[6] = (L - 2 * (H - vectorp[0])) - Open[1]; vectorp[0] = vectorp[0] - Open[1]; hi[0] = High[1]; hi[1] = High[2]; hi[2] = High[3]; hi[3] = High[4]; hi[4] = High[5]; lo[0] = Low[1]; lo[1] = Low[2]; lo[2] = Low[3]; lo[3] = Low[4]; lo[4] = Low[5]; H = hi[ArrayMaximum(hi)]; L = lo[ArrayMinimum(lo)]; vector[0] = (H + L + Close[1]) / 3; vector[1] = (2 * vector[0] - L) - Open[0]; vector[2] = (vector[0] + H - L) - Open[0]; vector[3] = (H + 2 * (vector[0] - L)) - Open[0]; vector[4] = (2 * vector[0] - H) - Open[0]; vector[5] = (vector[0] - H + L) - Open[0]; vector[6] = (L - 2 * (H - vector[0])) - Open[0]; vector[0] = vector[0] - Open[0]; MapLookup(vector, bmu); TLots = CalculateLotSize(); if ((bmu[0] < bmu[1]) && (bmu[0] < bmu[2])) Buy(); else if ((bmu[1] < bmu[0]) && (bmu[1] < bmu[2])) Sell(); Print("BMU Buy: ", bmu[0], " BMU Sell: ", bmu[1], " BMU Hold: ", bmu[2]); if ((NormalizeDouble((Open[0] - Open[1]), Digits) >= NormalizeDouble((MinPips*myPoint), Digits)) && (NormalizeDouble((Open[0] - Open[1]), Digits) <= NormalizeDouble((MaxPips*myPoint), Digits))) TeachMap(BUY_MAP, vectorp); else if ((NormalizeDouble((Open[0] - Open[1]), Digits) <= -NormalizeDouble((MinPips*myPoint), Digits)) && (NormalizeDouble((Open[0] - Open[1]), Digits) >= -NormalizeDouble((MaxPips*myPoint), Digits))) TeachMap(SELL_MAP, vectorp); else TeachMap(HOLD_MAP, vectorp); return(0); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { SaveKohonenMap(); } //+------------------------------------------------------------------+ //| Close all open orders | //+------------------------------------------------------------------+ void CloseAllOrders() { int total = OrdersTotal(); // Robert corrected loop order for proper close of Orders for(int pos = total - 1;pos >= 0; pos--) { if(OrderSelect(pos, SELECT_BY_POS) == true) { if (OrderMagicNumber() != Magic) continue; if (OrderSymbol() != Symbol()) continue; //Check for symbol int err = 0; int count = 0; while ((err != 1) && (count < 10)) { if (CheckOpenPositions() == 0) return; // Ue CheckOpenPosition in case other orders not of this EA are open count++; RefreshRates(); if (OrderType() == OP_SELL) err = OrderClose(OrderTicket(),OrderLots(),Ask,10,Violet); //Close position else if (OrderType() == OP_BUY) err = OrderClose(OrderTicket(),OrderLots(),Bid,10,Violet); //Close position } } } } // Robert modified for opening orders with ECN brokers void Buy() { int err; double TPprice,STprice; int result = -1; int count = 0; while ((result == -1) && (count < 10)) { RefreshRates(); count++; if (IsTradeAllowed()) { result = OrderSend(Symbol(),OP_BUY,TLots,Ask,Slippage,0,0,EAName,Magic,0, Green); if (result > 0) { OrderSelect(result, SELECT_BY_TICKET, MODE_TRADES); if (StopLoss != 0 || TakeProfit != 0) { TPprice = 0.0; if (TakeProfit > 0) TPprice=OrderOpenPrice() + TakeProfit * myPoint; STprice = 0.0; if (StopLoss > 0) STprice=OrderOpenPrice() - StopLoss * myPoint; // Normalize stoploss / takeprofit to the proper # of digits. if (Digits > 0) { STprice = NormalizeDouble( STprice, Digits); TPprice = NormalizeDouble( TPprice, Digits); } ModifyOrder(result, OrderOpenPrice(), STprice, TPprice, LightGreen); } } } if (result == -1) { err = GetLastError(); Print("OrderSend failed with error(" + err + ") " + ErrorDescription(err)); } } } // Robert modified for opening orders with ECN brokers void Sell() { int err; double TPprice,STprice; int result = -1; int count = 0; while ((result == -1) && (count < 10)) { RefreshRates(); count++; if (IsTradeAllowed()) { result = OrderSend(Symbol(),OP_SELL,TLots,Bid,Slippage,0,0,EAName,Magic,0, Red); if (result > 0) { OrderSelect(result, SELECT_BY_TICKET, MODE_TRADES); if (StopLoss != 0 || TakeProfit != 0) { TPprice = 0.0; if (TakeProfit > 0) TPprice = OrderOpenPrice() - TakeProfit * myPoint; STprice = 0.0; if (StopLoss > 0) STprice = OrderOpenPrice() + StopLoss * myPoint; // Normalize stoploss / takeprofit to the proper # of digits. if (Digits > 0) { STprice = NormalizeDouble( STprice, Digits); TPprice = NormalizeDouble( TPprice, Digits); } ModifyOrder(result, OrderOpenPrice(), STprice, TPprice, LightGreen); } } } if (result == -1) { err = GetLastError(); Print("OrderSend failed with error(" + err + ") " + ErrorDescription(err) ); } } } //+------------------------------------------------------------------+ //| Modify Open Position Controls | //| Try to modify position 3 times | //+------------------------------------------------------------------+ void ModifyOrder(int ord_ticket,double op, double price,double tp, color mColor) { int CloseCnt, err; CloseCnt=0; while (CloseCnt < 3) { if (OrderModify(ord_ticket,op,price,tp,0,mColor)) { CloseCnt = 3; } else { err=GetLastError(); Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err)); if (err>0) CloseCnt++; } } } void InitKohonenMap() { for (int i = 0; i < MAPBASE; i++) { for (int v = 0; i < VBASE; i++) { MapSell[i][v] = 0; MapBuy[i][v] = 0; } } for (i = 0; i < HOLDBASE; i++) { for (v = 0; i < VBASE; i++) { MapHold[i][v] = 0; } } } void MapLookup(double vector[], double& BMU[]) { BMU[0] = FindBMU(BUY_MAP, vector); BMU[1] = FindBMU(SELL_MAP, vector); BMU[2] = FindBMU(HOLD_MAP, vector); int i = 0; //BUY for (i = 0; i < MAPBASE; i++) { int z = 0; double vec[VBASE]; for (int v = 0; v < VBASE; v++) { if (MapBuy[i][v] == 0) z++; vec[v] = MapBuy[i][v]; } if (z == VBASE) break; double E = EuclidDistance(vec, vector); } //SELL for (i = 0; i < MAPBASE; i++) { z = 0; for (v = 0; v < VBASE; v++) { if (MapSell[i][v] == 0) z++; vec[v] = MapSell[i][v]; } if (z == VBASE) break; E = EuclidDistance(vec, vector); } //HOLD for (i = 0; i < HOLDBASE; i++) { z = 0; for (v = 0; v < VBASE; v++) { if (MapHold[i][v] == 0) z++; vec[v] = MapHold[i][v]; } if (z == VBASE) break; E = EuclidDistance(vec, vector); } } double FindBMU(int Buy, double vector[]) { int N = 0; if (Buy == 1) N = MAPBASE; else if (Buy == 0) N = MAPBASE; else N = HOLDBASE; double BestEuclidDistance = 9999999; double vec[VBASE]; for (int i = 0; i < N; i++) { double E; for (int v = 0; v < VBASE; v++) { if (Buy == 1) vec[v] = MapBuy[i][v]; else if (Buy == 0) vec[v] = MapSell[i][v]; else vec[v] = MapHold[i][v]; } E = EuclidDistance(vec, vector); if (E < BestEuclidDistance) { BestEuclidDistance = E; } } return(BestEuclidDistance); } double EuclidDistance(double VectorFromMap[], double vector[]) { double E = 0; for (int v = 0; v < VBASE; v++) { E += MathPow((VectorFromMap[v]*10000 - vector[v]*10000), 2); } E = MathSqrt(E); return(E); } void TeachMap(int Buy, double vector[]) { int BMUx = -1; int N; int x; if (Buy == 1) N = MAPBASE; else if (Buy == 0) N = MAPBASE; else N = HOLDBASE; for (x = 0; x < N; x++) { bool flag = false; for (int v = 0; v < VBASE; v++) { if (Buy == 1) {if (MapBuy[x][v] != 0) flag = true;} else if (Buy == 0) {if (MapSell[x][v] != 0) flag = true;} else {if (MapHold[x][v] != 0) flag = true;} } if (flag == false) break; } for (v = 0; v < VBASE; v++) { if (Buy == 1) MapBuy[x][v] = vector[v]; else if (Buy == 0) MapSell[x][v] = vector[v]; else MapHold[x][v] = vector[v]; } } void LoadKohonenMap() { int err; int handle = FileOpen(myMapPath, FILE_BIN|FILE_WRITE|FILE_READ); if (handle < 1) { err = GetLastError(); Print("File couldn't be opened; the last error is ", err, ":", ErrorDescription(err)); return(0); } FileReadArray(handle, MapBuy, 0, MAPBASE*VBASE); FileReadArray(handle, MapSell, 0, MAPBASE*VBASE); FileReadArray(handle, MapHold, 0, HOLDBASE*VBASE); FileClose(handle); } void SaveKohonenMap() { int err; int handle = FileOpen(myMapPath, FILE_BIN|FILE_WRITE|FILE_READ); if (handle < 1) { err = GetLastError(); Print("File couldn't be opened; the last error is ", err, ":", ErrorDescription(err)); return(0); } FileWriteArray(handle, MapBuy, 0, MAPBASE*VBASE); FileWriteArray(handle, MapSell, 0, MAPBASE*VBASE); FileWriteArray(handle, MapHold, 0, HOLDBASE*VBASE); } double GetPoint(string sym) { double _Point; int _Digits = MarketInfo(sym, MODE_DIGITS); if(_Digits < 4) _Point = 0.01; else _Point = 0.0001; return (_Point); } //+------------------------------------------------------------------+ //| Check Open Position Controls | //+------------------------------------------------------------------+ int CheckOpenPositions() { int cnt, NumPositions; int NumBuyTrades, NumSellTrades; // Number of buy and sell trades in this symbol NumBuyTrades = 0; NumSellTrades = 0; for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != Magic) continue; if(OrderType() == OP_BUY ) NumBuyTrades++; if(OrderType() == OP_SELL ) NumSellTrades++; } NumPositions = NumBuyTrades + NumSellTrades; return (NumPositions); } double CalculateLotSize() { double result = 0; if (Lots > 0) { result = Lots; } else { double startLots=1.0*MathSqrt(AccountBalance())/100; double pow2=1.0/Lots_Per_10K; double minLot=MarketInfo(Symbol(),MODE_MINLOT); result = FormatLotSize(MathMax(1.0*startLots/pow2,minLot)); } return(result); } double FormatLotSize(double dLots) { double lots=StrToDouble(DoubleToStr(dLots, C_LotStepDigits)); if(lots<C_MinLots) lots=C_MinLots; if(lots>MaxLots) lots=MaxLots; if(lots>C_MaxLots) lots=C_MaxLots; return(lots); }
对这个EA,做一个简单的测试,你就知道实际绩效不行的。 1.第一次测试,设定了时间,只测试一半就终止。这个时候,你就发现第一次测试部怎么行了。记住测试最后的交易时间。 2.重新开始测试。之前不行的绩效,却又变得非常吓人。但过了这之前的测试,后面的绩效又非常不堪入目。
我不明白你的这个测试具体是代指什么,因为在它的程序里面,有一段时间是要学习的,然后来利用学习的知识对未来发生的情况做判断。 我对这个算法的测试结果,也不怎么好,但是是因为我觉得他采用的数据太简单了,仅仅用high,low,close,open来做学习材料。 我把学习材料给改了,现在在商品期货上的测试效果非常好,他采用的学习算法的确是很有想法的。