初学者的问题 MQL5 MT5 MetaTrader 5 - 页 728

 

你好。我曾经在MetaTraider 4中写过一个专家顾问。或者说,我正在努力学习如何写。我不知道很多事情。我决定把它移植到MetaTraider 5上,结果发现有些不同。一般来说,我采取了另一个专家顾问。我把它拆开了。我已经复制了开盘赌注的代码。我没有错误,但它不像它应该的那样工作。帮助我正确移动它。

MetaTraider 4:

int  err = 0;            
double Lot = 0.01;       // Лот
double CoofLot = 0;
double Ballance = AccountBalance();
double loss = 100;    
bool nap = true;       //true  - 1
                       //false - 0
int start()
  {  
    if(OrdersTotal()==0)                                
    {
       if(Ballance != AccountBalance())                
       {
        if(AccountBalance() < Ballance )                
        {
            CoofLot++;
            Lot = pow(2, CoofLot) * 0.01;
            if(nap == true)                            
               {
                nap = false;
               }
             else
               {
                nap = true;
               }
         }
         if(AccountBalance() > Ballance)                
           {
             Lot = 0.01;
             CoofLot = 0;
           }
       }
    Ballance = AccountBalance();
    
    int order;
    if(nap == true)                                      
      {
       order = OrderSend(Symbol(),OP_BUY,Lot,Ask,1*Point,Ask-loss*Point,Ask+loss*Point);   // Вверх
      }                  
    else
      {
       order = OrderSend(Symbol(),OP_SELL,Lot,Bid,1*Point,Bid+loss*Point,Bid-loss*Point);    // Вниз
      }
  
       if(order<0)                                
         {
           if (GetLastError()==134)
             {
               err=1;
               Print("NOT ENOGUGHT MONEY!!");
             }
           return (-1);
         }
       }
   return(0);
  }


就这样转到了MetaTraider 5。

double Lot = 0.01;      
double CoofLot = 0;

double Ballance = ACCOUNT_BALANCE;
double loss = 100;    
bool nap = true;       //true  - 1
                       //false - 0



void OnTick()
{
   MqlTick latest_price;       // Будет использоваться для текущих котировок
   MqlTradeRequest mrequest;   // Будет использоваться для отсылки торговых запросов
   MqlTradeResult mresult;  
   if(OrdersTotal()==0)                                
      {
      if(!SymbolInfoTick(_Symbol,latest_price))
         {
            Alert("Ошибка получения последних котировок - ошибка:",GetLastError(),"!!");
            return;
         }
        
      if(Ballance != ACCOUNT_BALANCE)                
       {
        if(ACCOUNT_BALANCE < Ballance )                
        {
            CoofLot++;
            Lot = pow(2, CoofLot) * 0.01;
            if(nap == true)                            
               {
                nap = false;
               }
             else
               {
                nap = true;
               }
         }
         if(ACCOUNT_BALANCE > Ballance)                
           {
             Lot = 0.01;
             CoofLot = 0;
           }
       }
    Ballance = ACCOUNT_BALANCE;
    int order;
    if(nap == true)                                      
      {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.ask,_Digits);           // последняя цена ask
         mrequest.sl = NormalizeDouble(latest_price.ask - 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.ask + 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type = ORDER_TYPE_BUY;                                       // ордер на покупку
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order = OrderSend(mrequest,mresult);
      }                  
    else
      {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.bid,_Digits);           // последняя цена Bid
         mrequest.sl = NormalizeDouble(latest_price.bid + 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.bid - 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type= ORDER_TYPE_SELL;                                       // ордер на продажу
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order = OrderSend(mrequest,mresult);  
      }
      }
   return;
  }
 
DenZell:

你好。我曾经在MetaTraider 4中写过一个专家顾问。或者说,我正在努力学习如何写。我不知道很多事情。我决定把它移植到MetaTraider 5上,结果发现有些不同。一般来说,我采取了另一个专家顾问。我把它拆开了。我已经复制了开盘赌注的代码。我没有错误,但它不像它应该的那样工作。帮助我转移权利。


代码将是这样的(但要注意--有一个对交易账户上的总头寸数的检查(PositionsTotal)。

   if(PositionsTotal()==0)

也就是说,对于一个给定的符号和一个给定的魔术,没有检查到底有多少个位置(顺便说一下,魔术根本就没有设置))。

//+------------------------------------------------------------------+
//|                                                       TestEA.mq5 |
//|                              Copyright © 2016, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2016, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
//---
double         Lot            = 0.01;
double         CoofLot        = 1.0;
double         loss           = 100.0;
bool           nap            = true;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   CoofLot  = 1.0;
   loss     = 100.0;
   nap      = true;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   static double         Balance=0.0;
   if(Balance==0.0)
      Balance=AccountInfoDouble(ACCOUNT_BALANCE);

   if(PositionsTotal()==0)
     {
      MqlTick latest_price;                        // Будет использоваться для текущих котировок
      if(!SymbolInfoTick(_Symbol,latest_price))
        {
         Alert("Ошибка получения последних котировок - ошибка:",GetLastError(),"!!");
         return;
        }

      if(Balance!=AccountInfoDouble(ACCOUNT_BALANCE))
        {
         if(AccountInfoDouble(ACCOUNT_BALANCE)<Balance)
           {
            CoofLot++;
            Lot=pow(2,CoofLot)*0.01;
            if(nap==true)
              {
               nap=false;
              }
            else
              {
               nap=true;
              }
           }
         if(AccountInfoDouble(ACCOUNT_BALANCE)>Balance)
           {
            Lot=0.01;
            CoofLot=1.0;
           }
        }
      Balance=AccountInfoDouble(ACCOUNT_BALANCE);

      MqlTradeRequest mrequest;   // Будет использоваться для отсылки торговых запросов
      MqlTradeResult mresult;
      ZeroMemory(mrequest);
      ZeroMemory(mresult);

      bool order=false;
      if(nap==true)
        {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.ask,_Digits);           // последняя цена ask
         mrequest.sl = NormalizeDouble(latest_price.bid - 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.bid + 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type = ORDER_TYPE_BUY;                                       // ордер на покупку
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order=OrderSend(mrequest,mresult);
        }
      else
        {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.bid,_Digits);           // последняя цена Bid
         mrequest.sl = NormalizeDouble(latest_price.ask + 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.ask - 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type= ORDER_TYPE_SELL;                                       // ордер на продажу
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order=OrderSend(mrequest,mresult);
        }
     }
   return;
  }
//+------------------------------------------------------------------+

同时,OrderSend 操作的结果也是bool类型

我使用了一个静态变量来存储余额

   static double         Balance=0.0;
   if(Balance==0.0)
      Balance=AccountInfoDouble(ACCOUNT_BALANCE);

- 这意味着变量 "Balance "在OnTick()的后续操作中不会被重新创建,但它会记住它在前一个tick中的值。

附加的文件:
TestEA.mq5  10 kb
 

虽然我想这样写。

//+------------------------------------------------------------------+
//|                                                       TestEA.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.001"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\AccountInfo.mqh>
CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
CAccountInfo   m_account;                    // account info wrapper
//---
double         Lot            = 0.01;
double         CoofLot        = 1.0;
double         Loss           = 100.0;
bool           nap            = true;
//---
ulong          m_magic        = 15489;       // magic number
ulong          m_slippage     = 10;          // slippage
double         m_adjusted_point;             // point value adjusted for 3 or 5 points
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   m_symbol.Name(Symbol());                  // sets symbol name
   if(!RefreshRates())
     {
      Print("Error RefreshRates. Bid=",DoubleToString(m_symbol.Bid(),Digits()),
            ", Ask=",DoubleToString(m_symbol.Ask(),Digits()));
      return(INIT_FAILED);
     }
   m_symbol.Refresh();
//---
   m_trade.SetExpertMagicNumber(m_magic);
//---
   m_trade.SetDeviationInPoints(m_slippage);
//--- tuning for 3 or 5 digits
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   m_adjusted_point=m_symbol.Point()*digits_adjust;
//---
   CoofLot  = 1.0;
   Loss     = 100.0;
   nap      = true;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   static double         static_Balance=0.0;
   if(static_Balance==0.0)
      static_Balance=m_account.Balance();

   double balance=m_account.Balance();             // локальная переменная для хранения баланса на время OnTick

//--- считаем позиции по символу и по Magic
   int total=0;
   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of open positions
      if(m_position.SelectByIndex(i))     // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
            total++;

   if(total==0)
     {
      //--- попытка обновить цены
      if(!RefreshRates())
         return;                          // есил не удалось обновить цены - просто выходим

      if(static_Balance!=balance)
        {
         if(balance<static_Balance)
           {
            CoofLot++;
            double lots=pow(2,CoofLot)*0.01;       // локальная переменная для временных расчётов лота
            //--- проверка корректности лота
            Lot=LotCheck(lots);
            if(Lot==0.0)
               return;
            if(nap)
               nap=false;
            else
               nap=true;
           }
         if(balance>static_Balance)
           {
            Lot=0.01;
            CoofLot=1.0;
           }
        }
      static_Balance=balance;

      if(nap==true)
        {
         double sl=m_symbol.NormalizePrice(m_symbol.Bid() - Loss*m_adjusted_point); // Stop Loss
         double tp=m_symbol.NormalizePrice(m_symbol.Bid() + Loss*m_adjusted_point); // Take Profit

         if(m_trade.Buy(Lot,NULL,m_symbol.Ask(),sl,tp))
           {
            if(m_trade.ResultDeal()==0)
               Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
            else
               Print("Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
           }
         else
            Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
                  ", description of result: ",m_trade.ResultRetcodeDescription());
        }
      else
        {
         double sl=m_symbol.NormalizePrice(m_symbol.Ask()+Loss*m_adjusted_point); // Stop Loss
         double tp=m_symbol.NormalizePrice(m_symbol.Ask()-Loss*m_adjusted_point); // Take Profit

         if(m_trade.Sell(Lot,NULL,m_symbol.Ask(),sl,tp))
           {
            if(m_trade.ResultDeal()==0)
               Print("Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
            else
               Print("Sell -> true. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
           }
         else
            Print("Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
                  ", description of result: ",m_trade.ResultRetcodeDescription());
        }
     }
   return;
  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Lot Check                                                        |
//+------------------------------------------------------------------+
double LotCheck(double lots)
  {
//--- calculate maximum volume
   double volume=NormalizeDouble(lots,2);
   double stepvol=m_symbol.LotsStep();
   if(stepvol>0.0)
      volume=stepvol*MathFloor(volume/stepvol);
//---
   double minvol=m_symbol.LotsMin();
   if(volume<minvol)
      volume=0.0;
//---
   double maxvol=m_symbol.LotsMax();
   if(volume>maxvol)
      volume=maxvol;
   return(volume);
  }
//+------------------------------------------------------------------+

在这里。

  1. 止损设置为 "四倍 "点数--即它在欧元兑美元和美元兑日元上都能正常工作。
  2. CSymbolInfo 交易类的 "m_symbol "对象被用来获取价格。
  3. 我们检查给定符号和给定魔法的总头寸量。
  4. 如果改变批次,则事先在 "LotCheck "中进行检查和纠正。
  5. 交易操作是使用CTrade 交易类的 "m_trade "对象的方法进行的。
  6. 检查交易操作结果(两个步骤--基本检查和安置结果)。

已添加。

在策略测试器中得到了一个非常有趣的单次运行结果。

测试员


附加的文件:
TestEA.mq5  14 kb
 
Vladimir Karputov:

虽然我想这样写。

在这一点上,我不建议使用m_symbol.RefreshRates(),因为SymbolInfoTick()可能不会返回新鲜数据。而且,如果开发人员正在阅读这个主题,请再次提请他们注意SymbolInfoTick()搞砸了的 事实,但仍在SB类中使用!这是很重要的。
 
你好!我决定在MQL5中使用绿红蜡烛策略制作一个多货币专家顾问用于自学。
,基本功能已经实现,但一直出现 "无效价格 "等错误。我已经添加了一些额外的检查,以消除其可能的原因,并将其设置为当然正确的值,但错误并没有消失。我自己也不知道该走哪条路。能否请你告诉我,我哪里犯了错?我附上了源代码。
附加的文件:
 
NickWelder:
你好!我决定在MQL5中基于绿红烛策略制作一个多币种的专家顾问,用于自学。
我已经实现了基本功能,但一直收到 "价格无效 "之类的错误。我已经增加了额外的检查,以消除其可能的原因,并分别将其设置为已知的正确值,但错误并没有消失。我自己也不知道该走哪条路。能否请你告诉我,我哪里犯了错?我附上了源代码。

进行交易操作 之前,你需要更新交易类的CSymbolInfo对象中的价格。在我的单声道项目中(只有一个符号),我使用这个功能。

//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }

和用法 - 如果没有成功地更新价格,则直接退出,如果成功地更新价格,则会有一个交易操作。

//--- refresh rates
   if(!m_symbol.RefreshRates())
      return;

   if(m_trade.Buy(lots,NULL,m_symbol.Ask(),sl,tp))
     {
      if(m_trade.ResultDeal()==0)
         Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
               ", description of result: ",m_trade.ResultRetcodeDescription());
      else
         Print("Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
               ", description of result: ",m_trade.ResultRetcodeDescription());
     }
   else
      Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
            ", description of result: ",m_trade.ResultRetcodeDescription(
 
@Vladimir Karputov, 谢谢你!一切都在市场订单中运作。
 

有什么好的和 "简单 "的解决方案来取代这种设计?

if(iBarShift(_Symbol, _Period, TimeLast)==3) {...}

现在是这样的,但对我来说太 "重 "了。

int iBarShift(string symbol,ENUM_TIMEFRAMES tf,datetime time,bool exact=false) {
  if(time<0) return(-1);
   datetime Arr[],time1;
   CopyTime(symbol,tf,0,1,Arr);
   time1=Arr[0];
   if(CopyTime(symbol,tf,time,time1,Arr)>0) {
      if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
      if(time<time1) return(1);
      else return(0);
     }
   else return(-1);
}
 
Vitaly Muzichenko:

有什么好的和 "简单 "的解决方案来取代这种设计?

if(iBarShift(_Symbol, _Period, TimeLast)==3) {...}

现在是这样的,但对我来说太 "重 "了。

int iBarShift(string symbol,ENUM_TIMEFRAMES tf,datetime time,bool exact=false) {
  if(time<0) return(-1);
   datetime Arr[],time1;
   CopyTime(symbol,tf,0,1,Arr);
   time1=Arr[0];
   if(CopyTime(symbol,tf,time,time1,Arr)>0) {
      if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
      if(time<time1) return(1);
      else return(0);
     }
   else return(-1);
}
像这样(来自@fxsaber 的解决方案)。

//+------------------------------------------------------------------+
//| Возвращает смещение бара по времени                              |
//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=-1;
   datetime last_bar;
   if(SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)) {
      if(time>last_bar) res=0;
      else {
         const int shift=Bars(symbol_name,timeframe,time,last_bar);
         if(shift>0) res=shift-1;
         }
      }
   return(res);
}
//+------------------------------------------------------------------+
有人在某处写道,在选定的行中,你应该这样做:如果(time>=last_bar) res=0。

说实话,我没有检查过--我不是一直都能得到它。检查一下,请写出结果。
 
Vitaly Muzichenko:

有什么好的和 "容易 "的解决方案来取代这种设计?

if(iBarShift(_Symbol, _Period, TimeLast)==3) {...}

现在是这样的,但对我来说太 "重 "了。

int iBarShift(string symbol,ENUM_TIMEFRAMES tf,datetime time,bool exact=false) {
  if(time<0) return(-1);
   datetime Arr[],time1;
   CopyTime(symbol,tf,0,1,Arr);
   time1=Arr[0];
   if(CopyTime(symbol,tf,time,time1,Arr)>0) {
      if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
      if(time<time1) return(1);
      else return(0);
     }
   else return(-1);
}
我不知道我的解决方案有多 "轻",但试试这个:https://www.mql5.com/ru/forum/160945#comment_4053382
Как получить номер бара по времени входа в позицию?
Как получить номер бара по времени входа в позицию?
  • www.mql5.com
Приветствую! Пишу трейлинг, который проходится по барам начиная от времени входа в позицию...