Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 1415

 
Benjamin Fotteler #:
Спасибо за информацию. В разделе " Проверки, которые должен пройти торговый робот " упоминается метод "CheckMoneyForTrade", который проверяет, не превышает ли маржа, используемая для торговли, свободную маржу (ACCOUNT_FREE_MARGIN). Если я правильно вас понял, то вы также должны проверить, не превышают ли используемые средства определенный процент от баланса счета, т.е. что-то вроде:

При этом вы, конечно, можете изменить 0.9 на (1 - maxRisk) и реализовать свойство "Максимальный риск в %", которое может быть задано пользователем.

P.S. Мы тут на форуме на "ты" или на "ты"?

Все спотыкаются на размере лота, а тут куча кода и комментариев!

Сейчас я собрал воедино то, что Уильям Родер написал для MT5, это была бы непроверенная(!!) функция:
(https://www.mql5.com/en/forum/133792/page3#comment_3405179 & https://www.mql5.com/en/forum/390088#comment_28092477).

double lotsz (double risk, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   MqlTick mqTick;
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   SymbolInfoTick(sym,mqTick); 
   double diff = (ordDir==ORDER_TYPE_BUY) ? mqTick.ask - sl : ( (ordDir==ORDER_TYPE_SELL) ? sl - mqTick.bid : -1.0 );
   if (diff<0.0) return(0.0);
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   return( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
}
// use: lotsz(5, sl)

Пожалуйста, дайте мне знать, если вы найдете ошибку!

Так как большинство людей здесь так или иначе анонимны со своими никами или именами, а раньше это было еще более распространено, "Du" стало естественным.

Why is there NO Complete EA within the Code-Base? - When does the market close or open?
Why is there NO Complete EA within the Code-Base? - When does the market close or open?
  • 2011.08.20
  • www.mql5.com
I wanted to close all orders before end of the week (market close friday,) to prevent loss should the market gap over the week end, by passing the sl. ) so the question is when does the market close (or open. For example info on opened charts and history data, time info (like gmt, timezone, dst), market open, close info
 

Спасибо за код. Единственное, чего не хватает, - это адаптации к действительному промежуточному размеру лота:

double lotsz (double risk, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   MqlTick mqTick;
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   SymbolInfoTick(sym,mqTick); 
   double diff = (ordDir==ORDER_TYPE_BUY) ? mqTick.ask - sl : ( (ordDir==ORDER_TYPE_SELL) ? sl - mqTick.bid : -1.0 );
   if (diff<0.0) return(0.0);
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   lts = ( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return ((int)MathRound(lts/stepSize)*stepSize);
}
// use: lotsz(5, sl)

У меня есть еще один вопрос: если я рассчитываю убыток по стоп-ауту с помощью TICK_VALUE или с помощью deltaValue, как указано выше, результат всегда немного отличается от внутреннего расчета MQL5:

double price=(ordDir==ORDER_TYPE_BUY) ? mqTick.ask : ((ordDir==ORDER_TYPE_SELL) ? mqTick.bid : mqTick.last);
double loss;
OrderCalcProfit(ordDir, sym, 1, price, sl, loss)

Это связано с тем, что убыток/прибыль на тик отличается для счета EUR и для рыночной цены 1.0 и рыночной цены 1.2? Потому что если я ввожу, например, "price + 0.1" вместо price и "sl + 0.1" вместо sl в коде ниже, то расстояние между тиками (diff) одинаковое, но соответствующие результаты, выводимые OrderCalcProfit, разные. И когда я смотрю на прибыль/убытки, которые я получаю от ручных сделок, последнее, похоже, подтверждается.

Если я прав, то следующий код будет более точным:

double lotsz (double risk, double entry, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   double loss;
   OrderCalcProfit(ordDir, sym, 1, entry, sl, loss);
   double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / -loss);
   lts = (fmin(fmax(SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN), lts), SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return ((int)MathRound(lts / stepSize) * stepSize);
}
// use: lotsz(5, ask, sl)
P.S. Еще раз спасибо за основную идею: привязка фактора риска не к балансу, а к свободной марже явно имеет смысл.
 

Следующий код был создан в соответствии с собственным экспертом mql 5 по параболическому сару. Могу ли я изменить работу сигнала на покупку и сигнал на продажу? То есть, когда приходит сигнал на покупку, я хочу, чтобы он открывал продажи, а не покупки. может ли кто-нибудь помочь?




#property copyright "Copyright 2022, MetaQuotes Ltd."

#property link"https://www.mql5.com"

#property version "1.00"

//+------------------------------------------------------------------+

//| Include |

//+------------------------------------------------------------------+

#include <Expert\Expert.mqh>

//--- доступные сигналы

#include <Expert\Signal\SignalSAR.mqh>

//--- доступные трейлинги

#include <Expert\Trailing\TrailingNone.mqh>

//--- доступное управление деньгами

#include <Expert\Money\Money\MoneyFixedLot.mqh>

//+------------------------------------------------------------------+

//| Входы |

//+------------------------------------------------------------------+

//--- входные данные для эксперта

input string Expert_Title = "sar"; // Название документа

ulong Expert_MagicNumber =13831; //

bool Expert_EveryTick =false; //

//--- входы для основного сигнала

input int Signal_ThresholdOpen =10; //Пороговое значение сигнала для открытия [0...100]

input int Signal_ThresholdClose=10; //Пороговое значение сигнала для закрытия [0...100]

input double Signal_PriceLevel =0.0; // Уровень цены для совершения сделки

input int Signal_Expiration =4; // Истечение срока действия отложенных ордеров (в барах)

input double Signal_SAR_Step =0.02; // Приращение скорости параболического SAR(0.02,0.2)

input double Signal_SAR_Maximum =0.2; // Параболический SAR(0.02,0.2) Максимальная скорость

input double Signal_SAR_Weight =1.0; // Параболический SAR(0.02,0.2) Вес [0....1.0]

//--- входы для денег

input double Money_FixLot_Percent =10.0; // Процент

input double Money_FixLot_Lots =0.1; // Фиксированный объем

//+------------------------------------------------------------------+

//| Глобальный экспертный объект |

//+------------------------------------------------------------------+

CExpert ExtExpert;

//+------------------------------------------------------------------+

//| Функция инициализации эксперта |

//+------------------------------------------------------------------+

int OnInit()

{

//--- Инициализация эксперта

if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))

{

//----- не удалось

printf(__FUNCTION__+": ошибка инициализации эксперта");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Создание сигнала

CExpertSignal *signal=new CExpertSignal;

if(signal==NULL)

{

//----- не удалось

printf(__FUNCTION__+": ошибка создания сигнала");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//---

ExtExpert.InitSignal(signal);

signal.ThresholdOpen(Signal_ThresholdOpen);

signal.ThresholdClose(Signal_ThresholdClose);

signal.PriceLevel(Signal_PriceLevel);

signal.Expiration(Signal_Expiration);

//--- Создание фильтра CSignalSAR

CSignalSAR *filter0=new CSignalSAR;

if(filter0==NULL)

{

//----- не удалось

printf(__FUNCTION__+": ошибка создания фильтра0");

ExtExpert.Deinit();

return(INIT_FAILED);

}

signal.AddFilter(filter0);

//--- Устанавливаем параметры фильтра

filter0.Step(Signal_SAR_Step);

filter0.Maximum(Signal_SAR_Maximum);

filter0.Weight(Signal_SAR_Weight);

//--- Создание объекта трейлинга

CTrailingNone *trailing=new CTrailingNone;

if(trailing==NULL)

{

//----- не удалось

printf(__FUNCTION__+": ошибка создания трейлинга");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Добавляем трейлинг к эксперту (будет удален автоматически))

if(!ExtExpert.InitTrailing(trailing))

{

//----- failed

printf(__FUNCTION__+": ошибка инициализации трейлинга");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Устанавливаем параметры трейлинга

//--- Создание объекта денег

CMoneyFixedLot *money=new CMoneyFixedLot;

if(money==NULL)

{

//----- не удалось

printf(__FUNCTION__+": ошибка создания денег");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Добавляем деньги эксперту (будут удалены автоматически))

if(!ExtExpert.InitMoney(money))

{

//----- не удалось

printf(__FUNCTION__+": ошибка инициализации денег");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Устанавливаем параметры денег

money.Percent(Money_FixLot_Percent);

money.Lots(Money_FixLot_Lots);

//--- Проверяем параметры всех торговых объектов

if(!ExtExpert.ValidationSettings())

{

//----- не удалось

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Настройка всех необходимых индикаторов

if(!ExtExpert.InitIndicators())

{

//----- не удалось

printf(__FUNCTION__+": ошибка инициализации индикаторов");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- ok

return(INIT_SUCCEEDED);

}

//+------------------------------------------------------------------+

//| Функция деинициализации эксперта |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

ExtExpert.Deinit();

}

//+------------------------------------------------------------------+

//| Функция-обработчик события "Тик" |

//+------------------------------------------------------------------+

void OnTick()

{

ExtExpert.OnTick();

}

//+------------------------------------------------------------------+

//| Функция-обработчик события "Торговля" |

//+------------------------------------------------------------------+

void OnTrade()

{

ExtExpert.OnTrade();

}

//+------------------------------------------------------------------+

//| Функция-обработчик события "Таймер" |

//+------------------------------------------------------------------+

void OnTimer()

{

ExtExpert.OnTimer();

}

//+------------------------------------------------------------------+


 
Интересное предложение, я посмотрю. Функция OrderCalcProfit() существует только в MT5, а идеи расчета лота появились еще во времена MT4...
 
Я не могу открыть свою сессию в приложении, чтобы посмотреть, сколько у меня денег
 

У меня появилось время, чтобы разобраться с вашим решением. Оно более точное (в то время как другое более осторожное, так как учитывает комиссию?) и, очевидно, менее подвержено ошибкам, как видно на примере золота и серебра на демо-счете MQ - на Roboforex оно, как и ожидалось, несколько более осторожное, чем ваше решение:

MetaQuotes demo account (b. 3369 Beta channel)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   XAUUSD  in: 1717.65000 sl:1717.15000  diff:0.50000  delta:10.00000  delta:*diff:5.00000  tVal:0.10000  tSz:0.01000
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   XAGUSD  in: 18.45100 sl:18.40100  diff:0.05000  delta:500.00000  delta:*diff:25.00000  tVal:0.50000  tSz:0.00100
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   EURUSD  in: 1.02185 sl:1.02235  diff:0.00050  delta:97861.72139  delta:*diff:48.93086  tVal:0.97862  tSz:0.00001
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  XAUUSD  BU  in: 1717.65000  sl: 1717.15000  lotsC: 71.3100 (-3489.26)  lotsB: 10.2000 (-499.09)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  XAGUSD  BU  in: 18.45100  sl: 18.40100  lotsC: 18.4900 (-4523.66)  lotsB: 2.0400 (-499.09)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  EURUSD  SE  in: 1.02185  sl: 1.02235  lotsC: 9.8000 (-479.29)  lotsB: 10.2100 (-499.34)


RoboForex Demo account (b. 3320 release channel)
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   XAUUSD  in: 1717.10000 sl:1717.15000  diff:0.05000  delta:100.00000  delta:*diff:5.00000  tVal:0.10000  tSz:0.00100
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   XAGUSD  in: 18.43400 sl:18.43350  diff:0.00050  delta:5000.00000  delta:*diff:2.50000  tVal:0.05000  tSz:0.00001
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   EURUSD  in: 1.02186 sl:1.02236  diff:0.00050  delta:100000.00000  delta:*diff:50.00000  tVal:1.00000  tSz:0.00001
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  XAUUSD  SE  in: 1717.10000  sl: 1717.15000  lotsC: 38.2000 (-191.00)  lotsB: 53.4900 (-267.45)
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  XAGUSD  BU  in: 18.43400  sl: 18.43350  lotsC: 59.4300 (-148.57)  lotsB: 106.9700 (-267.42)
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  EURUSD  SE  in: 1.02186  sl: 1.02236  lotsC: 5.1400 (-257.00)  lotsB: 5.3500 (-267.50)

На счете MQ размеры лотов были бы слишком велики.

Вот мой скрипт для сравнения двух методов:

//+------------------------------------------------------------------+
//|                                            test_MM-functions.mq5 |
//|                                                            Calli |
//|                              https://www.mql5.com/de/users/gooly |
//+------------------------------------------------------------------+
#property copyright "Calli"
#property link      "https://www.mql5.com/de/users/gooly"
#property version   "1.00"
#property script_show_inputs
//--- input parameters
input double   risk_perCent   = 5.0;   // risk of capital in % on free_margin
input double   diff_sl        = 50;    // diff sl in points from entry
input double   CommPerLot     = 2.00;  

string Com = "",Syms[] = {"XAUUSD", "XAGUSD", "EURUSD" }; //,"AUDUSD","GBPCHF","GBPUSD", "EURCAD", "USDCAD", "USDRUB", "GBPJPY", "USDJPY"};

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
#define  forEach(TYPE, VAR, ARRAY) \
                TYPE VAR=NULL; \
                for(int i##VAR=0;  i##VAR<ArraySize(ARRAY)&&((VAR=ARRAY[i##VAR])!=NULL||true);  i##VAR++)

void OnStart()
  {
//---
   MqlTick mqTick;
   forEach(string, sym, Syms){
      
      double pnt = SymbolInfoDouble(sym,SYMBOL_POINT);
      ENUM_ORDER_TYPE ord = GetMicrosecondCount()%2==0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL; // randomly buy or sell
      SymbolInfoTick(sym,mqTick); 
      double entry = (ord==ORDER_TYPE_BUY) ? mqTick.ask : mqTick.bid,
             sl    = (ord==ORDER_TYPE_BUY) ? entry - diff_sl*pnt : entry + diff_sl*pnt,
             lossC = 0.0, lossB = 0.0,
             lotsC = lotszC(risk_perCent, entry, sl, sym, CommPerLot), 
             lotsB = lotszB(risk_perCent, entry, sl, sym, CommPerLot);
      
      if (!OrderCalcProfit(ord, sym, lotsC, entry, sl, lossC) ) 
         Print("chk OrderCalcProfit(",EnumToString(ord),", ",sym,", lot: ",lotsC,", in: ",DoubleToString(entry,6),", out: ",DoubleToString(sl,6),", lossC) => err: ",_LastError," lossC: ",lossC);
             
      if (!OrderCalcProfit(ord, sym, lotsB, entry, sl, lossB) ) 
         Print("chk OrderCalcProfit(",EnumToString(ord),", ",sym,", lot: ",lotsC,", in: ",DoubleToString(entry,6),", out: ",DoubleToString(sl,6),", lossC) => err: ",_LastError," lossC: ",lossC);
             
      string res = StringFormat("Set: Risk: %.1f %%, dSL: %.0f  Com/Lot: %.2f  Free: %.2f %s:  %s  %s  in: %.5f  sl: %.5f  lotsC: %.4f (%+.2f)  lotsB: %.4f (%+.2f)",
                                 risk_perCent, diff_sl, CommPerLot,
                                 AccountInfoDouble(ACCOUNT_MARGIN_FREE),AccountInfoString(ACCOUNT_CURRENCY),
                                 sym, (ord==ORDER_TYPE_BUY ? "BU" : "SE"), entry, sl, lotsC, lossC, lotsB, lossB );
      Com = Com + res+"\n";
   }
   Comment(Com);
   //Print(Com);
  }
//+------------------------------------------------------------------+
double lotszC (double risk, double entry, double sl, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   ENUM_ORDER_TYPE ordDir = entry > sl ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   double diff = fabs (entry - sl); 
   Print(sym,"  in: ",DoubleToString(entry,5)," sl:",DoubleToString(sl,5),"  diff:",DoubleToString(diff,5),
         "  delta:",DoubleToString(deltaValue,5),"  delta:*diff:",DoubleToString(deltaValue*diff,5),
         "  tVal:",DoubleToString(SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE),5),"  tSz:",
         DoubleToString(SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE),5));
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   lts = ( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return (MathRound(lts/stepSize)*stepSize);
}

double lotszB (double risk, double entry, double sl, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   ENUM_ORDER_TYPE ordDir = entry > sl ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   double loss;
   if (!OrderCalcProfit(ordDir, sym, 1, entry, sl, loss)) return(-1.0);
   double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / -loss);
   lts = (fmin(fmax(SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN), lts), SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return (MathRound(lts / stepSize) * stepSize);
}

Я вывел направление из in > sl (покупка) или in < sl (продажа). Тогда не будет проблем с отложенными ордерами

 

Спасибо за ваши тесты. Да, если сравнить результаты друг с другом, то можно увидеть, с одной стороны, согласованность OrderCalcProfit, а с другой стороны, по крайней мере, для EURUSD и RoboForex, что результаты отличаются примерно на "Lot size * CommissionPerLot". Это можно было бы добавить:

if (!OrderCalcProfit(ordDir, sym, 1, entry, sl, loss)) return(-1.0);
double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / (-loss + CommissionPerLot);
Если я правильно воспользовался поиском по форуму, то нет способа запросить значение "CommissionPerLot" напрямую с помощью MQL5, не так ли?
 
Benjamin Fotteler #:


Если я правильно воспользовался поиском по форуму, то в MQL5 нет возможности напрямую запросить значение "CommissionPerLot", верно?

Да, не напрямую в терминале, а запросить у брокера или в истории торговли: DEAL_COMMISSION.

Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Handelskonstanten / Eigenschaften der Deals
Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Handelskonstanten / Eigenschaften der Deals
  • www.mql5.com
Eigenschaften der Deals - Handelskonstanten - Konstanten, Enumerationen und Strukturen - Nachschlagewerk MQL5 - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5
 



Уважаемые участники~.


Я пытаюсь посчитать свечи. пожалуйста, помогите~~


int Barcount;

if(Barcount != Bars)

{ Barcount
Barcount = Bars;
pt = pt + 1;
}

Print("pt=",pt) ;


int OT,SHi;

if(OrderSelect(ticket,SELECT_BY_TICKET)==true)

{ }

OT = OrderOpenTime();

}

SHi = iBarShift(Symbol(),0,OT);

Print("SHi=",SHi);

 

Здравствуйте.

Дилетантский вопрос по CFD.

Кто-нибудь может объяснить природу свопов для CFD на коммодити/акции? Откуда он берется своп, начисляемый овернайт? Чем объясняется?

Причина обращения: