分享一个能自主学习的智能EA

Discussion in 'MetaTrader' started by ldawen, Sep 12, 2010.

  1. 个人学识有限,分享给大家研究。
    有点神奇,第一次测试时会自主训练,形成一个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);
    } 
    
     
  2. 楼主!有没有对没有学习过的数据进行测试啊?
    胜率和其他情况如何?
    我以前弄神经网络模型,对学习过的数据是拟合很好,可惜对未知数据不理想。
     
  3. 没测试,曾经用这个EA来挂机,基于5分钟的图,开单量很多,没怎么细究了,个人只会加减乘除。
     
  4. 学习一下。哈哈。
     
  5. 这个EA用的不是神经网络,我大致的看了一下代码,应该是一种基于否定式选择算法的分类器。等周末有时间再好好研究一下。

     
  6. 感觉这种学习的EA和未来函数一样的道理——对历史的意淫!
     
  7. 如果你认为未来真的是完全随机的,和过去没有任何关系,那么所有的学习算法都是在意淫...



     
  8. 研究一下这个系统的参数,无论用什么方法,参数越少未来重复历史测试的可能越大。当然,要有足够的交易次数。
     
  9. 对这个EA,做一个简单的测试,你就知道实际绩效不行的。
    1.第一次测试,设定了时间,只测试一半就终止。这个时候,你就发现第一次测试部怎么行了。记住测试最后的交易时间。
    2.重新开始测试。之前不行的绩效,却又变得非常吓人。但过了这之前的测试,后面的绩效又非常不堪入目。
     
  10. 这是典型的过拟合。基本上,对历史数据拟合的越好,适应能力就越差,也就是说对未来的外推能力就越差。
     
  11. 我不明白你的这个测试具体是代指什么,因为在它的程序里面,有一段时间是要学习的,然后来利用学习的知识对未来发生的情况做判断。

    我对这个算法的测试结果,也不怎么好,但是是因为我觉得他采用的数据太简单了,仅仅用high,low,close,open来做学习材料。

    我把学习材料给改了,现在在商品期货上的测试效果非常好,他采用的学习算法的确是很有想法的。

     
  12. 程序化交易应该属于技术分析这个大范畴,而技术分析三大假设,大家都没忘吧。
     
  13. 不好意思,技术分析三大假设是什么啊?:o
     
  14. 市场价格行为包容一切、价格以趋势方式演变以及历史会重演:)
     
  15. 流动性越强的时候, 技术分析越有效,