Не работает MarketInfo в тестере. - страница 2

 

stringo,

Не переживайте, пожалуйста так сильно, не надо. Я нигде и не утверждаю, что он работает или обязан работать.

Я понимаю ваши эмоции, сам работаю в тех-поддержке на форуме. Надо заметить, что ваш форум плохо структурирован (а проще говоря - одна большая свалка), поэтому найти нужную информацию в нём порой бывает весьма затруднительно.

Моя задача - правильно расчитать маржу на кроссах так, чтобы оно работало и в живую и в тестере.

На самом деле, начав с одной проблемы, откопал соседнюю. Обращаю внимание на моё замечание по iClose("EURUSD",0,0); Этот вызов действительно правильно заменяет MarketInfo и даёт валидную цену и в тестере и на счету. Но, как оказалось, встроенный в тестер маржиметр работает некорректно. Я вполне допускаю, что результаты по каждой сделке правильно приводятся к валюте счёта, если есть хистори, а может и не приводятся, - это совершенно не важно. Но расчёт допустимой маржи перед сделкой в тестере абсолютно точно никуда не приводится и работает только на основании текущего курса. Проверяется элементарно. Без всяких там вызовов я просто ручками вбиваю курс в расчёт маржи чуть ниже текущего и всё - сделка на полный объём свободных средств в тестере не состоится ни в какой момент исторического времени. Вбиваю чуть выше текущего - пройдёт любая сделка, независимо от реального курса на тот исторический момент.

Мне не надо полного моделирования соседних символов. Для того, чтобы моя задача в принципе имела решение, просто сделайте так (раз уж де-факто некоторые вызовы MarketInfo работают в тестере), чтобы MarketInfo (base, MODE_BID) и MarketInfo (base, MODE_ASK) возвращали тот внутренний курс, по которому работает сам тестер. Тестер в любом случае имеет какой-то курс, ему же как-то надо приводить результаты сделки к валюте счёта. Ну так отдайте мне этот курс. iClose("EURUSD",0,0) работает, но это не тот курс.

Но у меня появилась одна идея, я её набросаю, результатами обязательно поделюсь.

 

Идея прокатила. Не нужно расчитывать никаких сложных маржинальных формул. Вызов MarketInfo (symbol, MODE_MARGINREQUIRED) работает и на счету и в тестере. Причём в тестере работает, как и следовало ожидать, константно, основываясь только на текущей цене базовой валюты. Итоговый код расчёта объёма сделки в зависимости от запланированного риска выглядит чрезвычайно просто. Делюсь:

    // Normalize the volume to the account limitations
double NormalizeVolume (string symbol, double vol) {
  double  lotstep = MarketInfo (symbol, MODE_LOTSTEP);
  if ( lotstep<=0 )  return (0);

  vol = MathFloor(vol/lotstep)*lotstep;
  if ( vol<MarketInfo(symbol, MODE_MINLOT) )  vol = 0;
  return (MathMin (MarketInfo (symbol, MODE_MAXLOT), vol));
}


    // Calculate the volume of contract, using built-in means
double VolumeCalculate (string symbol, double risk) {
  double  leverage = AccountLeverage();
  double  margin = AccountFreeMargin();
  double  res = MarketInfo (symbol, MODE_MARGINREQUIRED);

  if ( margin<=0 || res<=0 )  return (0);
  res = margin/res;
  if ( risk<leverage )  res *= risk/leverage;

  return (NormalizeVolume(symbol, res));
}

Здесь две функции - расчёт объёма в лотах в зависимости от заданного риска, и нормализация этого объёма под требования ДЦ. Нормализация вынесена отдельно, поскольку она самоценна.

По ходу экспериментов заметил интересную вещь. Вызов MarketInfo (symbol, MODE_MARGINREQUIRED) даёт результат пригодный не только для покупки, но и для продажи (максимальная из двух маржей), хотя в документации указано, что результат только для покупки.

 

Красавчег :), отличная работа, есть некоторое замечание : возвращать " 0 " из функции я бы не рекомендовал можно нарваться на ERR_ZERO_DIVIDE 4013, и как следствие остановку системы, рекомендую возвращат отрицательное число, и проверять лот на положительность перед установкой ордера, дабы избежать 131 ошибки

 

Значение должно быть по возможности осмысленным. 0 - это осмысленное значение, означающее, что можно купить/продать 0 лотов. Искуственно вводить бессмысленные отрицательные значения не вижу стимула, тем более, что "проверку лота на положительность перед установкой ордера" надо делать по любому, хотя бы потому, что 0 может получиться и сам по себе, в результате математических операций. Искуственный 0, как и естественный, такую проверку не пройдёт.

 
Shaitan писал(а) >>

Значение должно быть по возможности осмысленным. 0 - это осмысленное значение, означающее, что можно купить/продать 0 лотов. Искуственно вводить бессмысленные отрицательные значения не вижу стимула, тем более, что "проверку лота на положительность перед установкой ордера" надо делать по любому, хотя бы потому, что 0 может получиться и сам по себе, в результате математических операций. Искуственный 0, как и естественный, такую проверку не пройдёт.

Это конечно дело ваше, но при осмысленном значении "0" можно весело нарваться на зеродивайд и полную остановку советника...

 
Shaitan писал(а) >>

Идея прокатила. Не нужно расчитывать никаких сложных маржинальных формул. Вызов MarketInfo (symbol, MODE_MARGINREQUIRED) работает и на счету и в тестере. Причём в тестере работает, как и следовало ожидать, константно, основываясь только на текущей цене базовой валюты. Итоговый код расчёта объёма сделки в зависимости от запланированного риска выглядит чрезвычайно просто. Делюсь:

Здесь две функции - расчёт объёма в лотах в зависимости от заданного риска, и нормализация этого объёма под требования ДЦ. Нормализация вынесена отдельно, поскольку она самоценна.

По ходу экспериментов заметил интересную вещь. Вызов MarketInfo (symbol, MODE_MARGINREQUIRED) даёт результат пригодный не только для покупки, но и для продажи (максимальная из двух маржей), хотя в документации указано, что результат только для покупки.

есть ошибка. скорее всего связана с использованием AccountLeverage();

я использую вот такую формулу

lot=AccountFreeMargin()/MarketInfo (Symbol(), MODE_MARGINREQUIRED)*(Risk/100.0);

Для проверки вашего кода поставил риск 100% и смог открытся 18 лотами. В то время как ваша функция показывала в 5 раз меньше лот. (ДЦ альпари Leverage= 500)

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

 
Prival писал(а) >>

lot=AccountFreeMargin()/MarketInfo (Symbol(), MODE_MARGINREQUIRED)*(Risk/100.0);

Для проверки вашего кода поставил риск 100% и смог открытся 18 лотами. В то время как ваша функция показывала в 5 раз меньше лот. (ДЦ альпари Leverage= 500)

Это не ошибка. Это идеологический момент. Посмотрите, в моей функции есть такая строка:

if ( risk<leverage ) res *= risk/leverage;
Математически ваше преобразование и моё - почти эквивалентны. И в том и в другом случае риск означает линейное масштабирование объёма. НО!!! в вашем случае перенос кода с одного ДЦ на другой (или смена типа счёта) может вызвать катастрофу при условии, что на счетах разный leverage. Вы отладили ваш вариант расчёта объёма на плече 100, перенесли советник на счёт с плечём 500 и... опа! советник откроет позицию в пять раз больше, чем на первом счету. Если вы, к примеру, заложили в money management допустимые убытки 20%, то на втором счету можете ненароком слить всё.

В моём же случае, расчёт всегда даёт такой объём, который успешно откроется, но при этом на любом счету это будет гарантировано один и тот же объём. Risk в данном случае формально - принудительное ограничение плеча, а реально - масштаб объёма, который откроется. Но только не надо воспринимать его как проценты. Скорей, просто как величину. 100 - много. 500 - запредельно много :)

Поставьте в вызов моей функции risk=500 и вы получите правильный объём для вашего случая.

Особенное если есть уже открытые позиции и по разным инструментам, то там вообще головная боль.

Тут я с вами полностью согласен. Но задача наверняка решаема.
 
Shaitan писал(а) >>


Математически ваше преобразование и моё - почти эквивалентны.

почему почти, полностью. Отличие вы делите на Leverаdge, я на 100.

Я понимаю что каждый делает расчет лота под себя. Но всегда считал, что если задаешь риск 100% это и есть 100% = вход по самые помидоры :-), все большим лотом (ни на цент больше) открыться нельзя. Функция должна учитывать по возможности все.

Потом просто регулируешь риск. В вашем варианте по самые помидоры не получается, поэтому и при риске 1%, то же будет не точен расчет.

з.ы.думаю надо как то доробатать под себя. что бы 100 было 100 и при этом плечо учитывалось.

 

100% это и есть 100% = вход по самые помидоры :-)

Проценты бывают и больше 100.

Чтобы было "по самые помидоры", просто ставьте сразу 1000%. Максимальный возможный объём и ни центом больше гарантирован на любом счету. Но мне ка-ца, что при таком подходе можно очень быстро распрощаться с помидорами.

Чтобы и 100 было 100, и плечо учитывалось - взаимоисключающие требования. Это невозможно.

 
stringo:

А как он будет работать, если соседние символы не моделируются? А если соседние символы моделируются, то тут же и портфельное тестирование рядышком лежит. А для четвёрки это слишком серьёзное изменение, связанное с полной сменой архитектуры тестера.

Тема старенькая, 4-летняя но я вчера столкнулся с этой же проблемой. Тоесть явно портфельное моделирование в тестере все еще не сделано? В связи с этим 2 вопроса:

1. Планов добавить это в ближайшем будущем есть? (MT4)

2. В MT5 ситуация такая же или там работает?

..имеется ввиду портфельная тоговля в тестере или хотя бы MarketInfo (или ее MT5-еквивалент)?