Простой торговый робот - страница 3

 
OneBillionUSD:

И снова добрый день!)

Хочу написать функцию, которая будет определять нужный объем сделки  от некоторого процента депозита. Для этого мне нужно знать:

 Вот стоимость шага я не могу определить или его считать равным?

 

Не даром говорят что правильно заданный вопрос это как минимум 2/3 ответа... :)

А теперь приступим к делу.

Шаг №1 - сформулируем нашу задачу, а она такова:

Написать функцию (или набор функций) для расчета размеров лотов от некоторого процента депозита. Насколько я понимаю, под ДЕПОЗИТОМ понимается не баланс, а именно свободные средства...

Шаг №2 - Определяем объем выполняемой работы и остальные вводные:

Насколько я понимаю нам понадобится ДВЕ функции:

1. Рассчитывает размер средств которые могут быть ОТДАНЫ В ЗАЛОГ при открытии новой позиции, расчет ведется по указанному проценту от свободных средств;

2. Возвращает МИНИМАЛЬНЫЙ размер лота для нового ордера или позиции

Что нам понадобится для расчетов:

1. Процент по которому будет рассчитываться оптимальный размер залога;

2. Размер свободных средств;

3. Размер торгового плеча (скажем, 100 или 500);

4. Минимальный размер лота для данного инструмента;

5. Максимальный размер лота для данного инструмента;

6. Шаг наращивания размера лота

7. Другие данные, которые возможно понадобятся


PS

Тут не учитывается уже существующие позиции и отложники...

 
OneBillionUSD:

Хочу написать функцию, которая будет определять нужный объем сделки  от некоторого процента депозита. Для этого мне нужно знать...


Продолжим... :)

Шаг №3 - Расчет оптимальной суммы для залога:

Как все мы тут понимаем это должна быть функция возвращающая  double, пусть это будет например - double MarginOptimumSize().

Я так думаю что параметрами для нее вполне могут стать: свободных средств, процент и торговое плечо (при этом два последних параметра будут объявлены на прямую, что позволит не указывать их при вызове функции).

Шаблон функции будет выглядеть тогда примерно так:

//Function MarginOptimumSize
double MarginOptimumSize(double FreeMargin,double Percent=10.0,long Leverage=100)
//Функция производит расчет оптимального размера залога для ордера или позиции
{
//----------------------------------------------------------------------------//
//Служебные переменные
double Result;//Возвращаемое значение
//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//
return(Result);
//----------------------------------------------------------------------------//
}
 
Interesting:


Что нам понадобится для расчетов:

1. Процент по которому будет рассчитываться оптимальный размер залога;

2. Размер свободных средств;

3. Размер торгового плеча (скажем, 100 или 500);

4. Минимальный размер лота для данного инструмента;

5. Максимальный размер лота для данного инструмента;

6. Шаг наращивания размера лота

7. Другие данные, которые возможно понадобятся


PS

Тут не учитывается уже существующие позиции и отложники...


1. Это входной параметр;

2. Это AccountInfoDouble(ACCOUNT_FREEMARGIN);

3. Мне пока не ясно для чего нам нужно знать это. Объясните пожалуйста;

4. Это SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN); 

5. Это SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);

6. Это SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP); 

 

Имея шаблон функции прикинем ее начинку.

Шаг №4 - Функция double MarginOptimumSize(): 


//Function MarginOptimumSize
double MarginOptimumSize(double FreeMargin=0.0,double Percent=10.0,long Leverage=100)
//Функция производит расчет оптимального размера залога для ордера или позиции
{
//----------------------------------------------------------------------------//
//Служебные переменные
double Margin; //Сумма залога
double Result; //Возвращаемое значение
//----------------------------------------------------------------------------//
//Защита от дурака!
  if(FreeMargin<=0.0)
  {
  FreeMargin = AccountInfoDouble(ACCOUNT_FREEMARGIN);
  }
//Произведем расчет залога исходя из Leverage = 100 (Плечо 100 как стандарт)
Margin = (FreeMargin/100)*Percent;
//Оптимизируем сумму залога под реальный Leverage (предпологаем что Leverage>=100)
  if(Leverage==100)
  //Счет со стандартным торговым плечом в 100
  {
  Result = Margin; //Раз плечо стандартно оптимизация не нужна!
  }
  else
  //Особые условия, выполним оптимизацию
  {
  Result = Margin/NormalizeDouble(Leverage/100,2);
  }
//----------------------------------------------------------------------------//
return(Result);
//----------------------------------------------------------------------------//
}

PS

Оптимизация под реальный Leverage для избежания ошибки расчета на торговых счетах где плечо > 100.

 

Теперь займемся основной функцией.

Шаг №5 - Функция double LotOptimumSize():

Рассчитать оптимальную сумму средств для залога это еще не все что нам надо, нам нужна вторая функция, скажем - double LotOptimumSize().

Параметрами для данной функции нам как минимум должны будут служить имя символа и оптимальный залог (возвращаемый функцией MarginOptimumSize())

Для расчета размера лота нам также понадобится и залог для стандартного лота, который лучше рассчитать отдельно, а тут использовать как дополнительный параметр.


Таким образом шаблон данной функции будет выглядеть примерно так:

//Function LotOptimumSize
double LotOptimumSize(string WorkSymbol,double MarginOptimal=0.0,double MarginStd=0.0)
//Функция производит расчет оптимального размера лота для ордеров и позиций
{
//----------------------------------------------------------------------------//
//Служебные переменные
//Минимальный и максимальный размеры лотов, а также шаг
double SymbolLotMin,SymbolLotMax,SymbolLotStep;
double StepSumm,LotStepCount; //Необходимы для расчета лота
double LotSize; //Размер лота
double Result;  //Возвращаемое значение
//----------------------------------------------------------------------------//
//Защита от дурака!
  if(MarginOptimal<=0.0)
  {
  MarginOptimal = MarginOptimumSize(AccountInfoDouble(ACCOUNT_FREEMARGIN));
  }
//Получаем вилку по размерам лота
SymbolLotMin  = SymbolInfoDouble(WorkSymbol,SYMBOL_VOLUME_MIN);  //Минимальный лот
SymbolLotMax  = SymbolInfoDouble(WorkSymbol,SYMBOL_VOLUME_MAX);  //Максимальный лот
SymbolLotStep = SymbolInfoDouble(WorkSymbol,SYMBOL_VOLUME_STEP); //Шаг лотов
//Расчитываем размер лота
  if(MarginOptimal<MarginStd)
  //Указанной маржи не достаточно для открытия хотябы одного стандартного лота
  //Необходимо получить размер лота который мы можем открыть
  {
  LotSize = NormalizeDouble(MarginStd/MarginOptimal,2);
  }
  else
  //Достоточно маржи для открытия как минимум одного стандартного лота
  {
  LotSize = NormalizeDouble(MarginOptimal/MarginStd,2);
  }
//Оптимизируем размер лота под торговые условия
//Оптимизация. Шаг №1 - Проверка на мин и макс значения размера лота
  if(LotSize<SymbolLotMin){LotSize=SymbolLotMin;} //Лот меньше минимального
  if(LotSize>SymbolLotMax){LotSize=SymbolLotMax;} //Лот больше максимального
//Оптимизация. Шаг №2 - Перерасчет размера лота
  if(LotSize>SymbolLotMin)
  {
  StepSumm = LotSize-SymbolLotMin;
  LotStepCount = StepSumm/SymbolLotStep-NormalizeDouble(MathMod(StepSumm/SymbolLotStep,1.0),2);
  LotSize = SymbolLotMin+LotStepCount*SymbolLotStep;
  }
Result = LotSize;
//----------------------------------------------------------------------------//
return(Result);
//----------------------------------------------------------------------------//
}

Шаг №6 - Расчет суммы залога по стандартному лоту

Вот и остался последний этап, создать последнюю функцию для расчета залога по стандартному лоту.

Не буду долго ее описывать, скажу только, что для расчета залога по EUR проще всего использовать такую формулу:

Залог = Lot*OpenPrice/Leverage;

где:

Lot - размер лота в базовой валюте (для стандартного контракта - SYMBOL_TRADE_CONTRACT_SIZE);

OpenPrice - Текущая цена открытия позиции или ордера

Leverage - Размер предоставленного плеча (ACCOUNT_LEVERAGE)

 
OneBillionUSD:

3. Мне пока не ясно для чего нам нужно знать это. Объясните пожалуйста;


Это объясняется тем что при расчете залога для счетов с разным Leverage необходимо его учитывать.

Для иллюстрации приведу два примера расчета для залога по EUR для счетов различающихся только Leverage (100 и 500)


Вводные

Свободно средств - 25000 $

Процент от депозита - 10%

Минимальный лот - 0.10

Шаг изменения - 0,01


Рассчитываем залог по проценту от свободных средств

2500$ = (25000/100)*10 - верно для счетов где Leverage = 100 (но не верно для счетов с плечом > 100)

500$ = (25000/500)*10 - верно для счетов где Leverage = 500 (но не верно для счетов с плечом < 500)


Расчет залога для стандартного лота

1267.7$ = (100000*1.2677)/100 - верно для счетов где Leverage = 100 (но не верно для счетов с плечом > 100)

253.54$ = (100000*1.2677)/500 - верно для счетов где Leverage = 500 (но не верно для счетов с плечом < 500)


 
Interesting:

Имея шаблон функции прикинем ее начинку.

Шаг №4 - Функция double MarginOptimumSize()...



Данная функция не совсем подходит для универсального расчета, вот более совершенная (на мой взгляд) функция:

//Function MarginOptimumSize
double MarginOptimumSize(double FreeMargin=0.0,double Percent=10.0,long Leverage=100)
//Функция производит расчет оптимального размера залога для ордера или позиции
{
//----------------------------------------------------------------------------//
//Служебные переменные
double Margin; //Сумма залога
double Result; //Возвращаемое значение
//----------------------------------------------------------------------------//
//Защита от дурака!
  if(FreeMargin<=0.0)
  {
  FreeMargin = AccountInfoDouble(ACCOUNT_FREEMARGIN);
  }
//Произведем расчет залога исходя из Leverage = 100 (Плечо 100 как стандарт)
Margin = (FreeMargin/100)*Percent;
//Оптимизируем сумму залога под реальный Leverage (предпологаем что Leverage>=100)
  if(Leverage==100)
  //Счет со стандартным торговым плечом в 100
  {
  Result = Margin; //Раз плечо стандартно оптимизация не нужна!
  }
  else
  //Особые условия, выполним оптимизацию
  {

    if(Leverage>100)
    //Плечо больше 100
    {
    Result = Margin/NormalizeDouble(Leverage/100,0);
    }
    else
    //плечо меньше 100
    {
    Result = Margin/NormalizeDouble(100/Leverage,0);
    }

  }
//----------------------------------------------------------------------------//
return(Result);
//----------------------------------------------------------------------------//
}

PS

Тут я исправил расчет залога для счетов где Leverage<>100.

Подразумевается, что при плече меньше 100 необходимо средств больше, а при плече больше 100 - меньше...

 
Interesting:


Данная функция не совсем подходит для универсального расчета, вот более совершенная (на мой взгляд) функция:

PS

Тут я исправил расчет залога для счетов где Leverage<>0.

Подразумевается, что при плече меньше 100 необходимо средств больше, а при плече больше 100 - меньше...

Спасибо большое за пример! Очень он мне помог!
 
CoreWinTT:

         MqlTradeRequest BigDogBuy;
         MqlTradeRequest BigDogSell;
         ...
         MqlTradeResult ResultBuy,ResultSell;
         OrderSend(BigDogBuy,ResultBuy);
         OrderSend(BigDogSell,ResultSell);
Подскажите, пожалуйста, как грамотно оформить код, если используемая стратегия требует выставления второго приказа (в примере - OrderSend(BigDogSell,ResultSell)) только после успешного размещения первого отложенного ордера OrderSend(BigDogBuy,ResultBuy). Иными словами, как грамотно подстраховаться от выставления советником второго ордера, если по каким -либо причинам терминал в течение некоторого времени не получает от сервера сигнал об успешном размещении первого отложенного ордера?
 
Yedelkin:
Подскажите, пожалуйста, как грамотно оформить код, если используемая стратегия требует выставления второго приказа (в примере - OrderSend(BigDogSell,ResultSell)) только после успешного размещения первого отложенного ордера OrderSend(BigDogBuy,ResultBuy). Иными словами, как грамотно подстраховаться от выставления советником второго ордера, если по каким -либо причинам терминал в течение некоторого времени не получает от сервера сигнал об успешном размещении первого отложенного ордера?
Возможно вам подойдет эта статья https://www.mql5.com/ru/articles/40
Обработка торговых событий в эксперте при помощи функции OnTrade()
Обработка торговых событий в эксперте при помощи функции OnTrade()
  • 2010.06.01
  • KlimMalgin
  • www.mql5.com
В 5-ой версии языка MQL появилась масса нововведений, в том числе работа с событиями различных типов (события таймера, торговые события, пользовательские и т.д.). Возможность обработки событий позволяет создавать совершенно новый тип программ для автоматического и полуавтоматического трейдинга. В этой статье мы рассмотрим торговые события и напишем для функции OnTrade() код, который будет обрабатывать событие Trade.
Причина обращения: