Вопросы от начинающих 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 на коммодити/акции? Откуда он берется своп, начисляемый овернайт? Чем объясняется?