Особенности языка mql5, тонкости и приёмы работы - страница 157

 
Andrey Khatimlianskii:

Привет!

Аналог офф-лайн чартов МТ4 - это кастумные инструменты. Можно залить любую историю, в т.ч. сделать 1 бар = 1 тику.

Но, как и в МТ4, каждый бар должен минимум на минуту отличаться по времени от предыдущего, поэтому нормальной шкалы времени не будет.

ps: вот тут готовый индикатор есть -  https://www.mql5.com/en/blogs/post/719145

в МТ4 время бара просто должно быть больше предыдущего бара и тогда МТ4 отобразит бар, т.е. в МТ4 можно с точностью до секунд рисовать бары на оффлайновых графиках, я в КБ выкладывал секундный чарт

но с МТ5 такой фокус "не прокатит", если попробовать в кастомный символ отправить 2 бара у которых время открытия будет одинаковым без учета секунд, то отобразится только один бар, т.е. точность меньше М1 на кастомных графиках МТ5 не получится

 
fxsaber:

Здесь схема. Работает.

Без передвижения ТП? Прямо каждый раз срабатывает? Не более, чем везение.


fxsaber:

Где та самая граница идеальности, с которой можно/нужно мириться? Какое отношение случающиеся иногда реджекты и реквоты имеют к Тестеру?

Реджекты не при чем.

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

Другой вопрос, что в режиме 0-й задержки (идеального исполнения), тестер мог бы делать вид, что ордер был отправлен брокеру и исполнен мгновенно, но пользы в этом ни какой не вижу, т.к., повторюсь, не вижу смысла в идеальном тестировании, если в реале все равно будет иначе.

 
Igor Makanu:

в МТ4 время бара просто должно быть больше предыдущего бара и тогда МТ4 отобразит бар, т.е. в МТ4 можно с точностью до секунд рисовать бары на оффлайновых графиках, я в КБ выкладывал секундный чарт

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

В пятерке точно нельзя так.

 
Andrey Khatimlianskii:

Привет!

Аналог офф-лайн чартов МТ4 - это кастумные инструменты. Можно залить любую историю, в т.ч. сделать 1 бар = 1 тику.

Но, как и в МТ4, каждый бар должен минимум на минуту отличаться по времени от предыдущего, поэтому нормальной шкалы времени не будет.

ps: вот тут готовый индикатор есть -  https://www.mql5.com/en/blogs/post/719145

О, пользовательские символы - это как раз то, что надо ! А время тика для меня роли не играет. Спасибо, это импульс в нужном направлении. )))

 
Andrey Khatimlianskii:

Без передвижения ТП? Прямо каждый раз срабатывает? Не более, чем везение.

Нет, конечно. Поэтому и цикл.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Особенности языка mql4, тонкости и приёмы работы

fxsaber, 2019.12.13 00:27

Схематично срочное закрытие позиции делаю так
const double ClosePrice = OrderType() ? MathMin(OrderClosePrice(), Bid + MaxSpread * _Point) 
                                      : MathMax(OrderClosePrice(), Ask - MaxSpread * _Point);
    
OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), ClosePrice, 0); // StopLoss оставлен для истории
В цикле, конечно. Есть другие варианты?

Реджекты не при чем.

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

Другой вопрос, что в режиме 0-й задержки (идеального исполнения), тестер мог бы делать вид, что ордер был отправлен брокеру и исполнен мгновенно, но пользы в этом ни какой не вижу, т.к., повторюсь, не вижу смысла в идеальном тестировании, если в реале все равно будет иначе.

В реале будет либо полное (либо частичное) исполнение по текущей цене (или лучше), либо реджект. Т.е. исполнение может быть как идеальным, так и отсутствовать.

Получаем, что Тестер для маркета всегда исполняет идеально, а для лимитника - всегда нет.

 
fxsaber:

Получаем, что Тестер для маркета всегда исполняет идеально, а для лимитника - всегда нет.

Вот я бы скорее для маркетов сделал исполнение следующим тиком. Лучше тестер покажет слив, чем реал. А грааль вряд ли от этого потеряется.

 
Andrey Khatimlianskii:

Вот я бы скорее для маркетов сделал исполнение следующим тиком. Лучше тестер покажет слив, чем реал. А грааль вряд ли от этого потеряется.

Следующим тиком не верно, ваш маркет должен порождать тик, и исполнятся по ближайшим бидам или аскам, с учётом объёма сделки.
Лимитник так же, должен заполнятся по гарантированной цене с учётом объёма.
Все другие алгоритмы которые сейчас сделаны, только вводят в заблуждение, получения реальных результатов.
По этой причине тестером не пользуюсь вообще. Нет смысла, когда на самих основах, идёт подмена исполнения. 

 
Roman:

Следующим тиком не верно, ваш маркет должен порождать тик, и исполнятся по ближайшим бидам или аскам, с учётом объёма сделки.
Лимитник так же, должен заполнятся по гарантированной цене с учётом объёма.
Все другие алгоритмы которые сейчас сделаны, только вводят в заблуждение, получения реальных результатов.
По этой причине тестером не пользуюсь вообще. Нет смысла, когда на самих основах, идёт подмена исполнения. 

Ну, для этого нужна история стакана или, как минимум, объемы крайних бид/аск. А их нет.

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

 
Andrey Khatimlianskii:

Ну, для этого нужна история стакана или, как минимум, объемы крайних бид/аск. А их нет.

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

Как заявлял один из модераторов, что мт5 разрабатывался для биржевых рынков,
но смотря на реализацию тестера, его разработка свелась к тому же принципу дилингового исполнения, даже на реальных тиках.
 
Как вы вообще тогда тестируете? На каких исторических данных? 
И потом доверяете тестам на таких исторических котировках?
:))

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

Да согласен, что сейчас не сохраняются объемы для бид аск, но что мешает разработчикам добавить три колонки ! 

  1. Колонка объёма Ask
  2. Колонка объёма Bid
  3. Колонка направления Last сделки, Buy или Sell


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

Да, про порождающий тик, не так выразился, имелось ввиду что маркет в тестере должен исполнятся по ближайшим Бидам Аскам, собирая ликвидность на уровнях цен.
То есть если мы отправляем BuyMarket объемом 25, то цена исполнения соберёт два уровня, 10 и 15, и автоматически усреднит чистую цену позиции.

182.13   Ask1  15
182.12   Ask0  10
--------------------
182.11   Bid0   5
182.10   Bid1   8 

А для лимитных заявок, объём Last сделок должен заполнять объём вашей лимитной заявки, по той гарантированной цене по которой выставлена лимитка.  
То есть заполнение лимитной заявки должно быть частичным. Если ваша лимитная заявка выставлена с объёмом 25, то прошедшая Last сделка с объемом 5, откусит от вашей заявки 5.
Ваша лимитная заявка теперь стоит с объём 20, следующая Last сделка прошла с объемом 10, ваша лимитная заявка теперь стоит с объёмом 10,
прошёл ещё Last с объёмом 10, ваша лимитная заявка полностью заполнена.
Если цена развернулась и не исполнила весь объём лимитной заявки, такова реальная ситуация, реального исполнения.
И ваш остаточный объем лимитки продолжает ждать пока снова не придёт к ней Last, или вы не снимите эту заявку сами.

По этому, в таком виде как реализован сейчас алгоритм исполнения в тестере, ну ничего не имеет общего с реальностью.
Аля игрушка с замыливанием глаз.


 

Вожусь не со своими POD-структурами для вскрытия одного формата. В структурах много полей. Некоторые структуры наследуются, какие-то имеют приватные поля.


В общем, возникла задача обнуления этих структур, чтобы редактировать исследуемый формат. И ничего толком не выходит. В итоге стал использовать такой вариант.

#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

// Обнуление переменной.
template <typename T>
void ToNull( T &Value )
{
  uchar Bytes[sizeof(T)];
  ArrayInitialize(Bytes, 0);
  
  _W(Value) = Bytes;
}


Применение.

struct A
{
private:
  int i;
  
public:
  int j;  
};

void OnStart()
{
//  A a = {0};     // 'a' - cannot be initialized with initializer list
//  ZeroMemory(a); // 'a' - not allowed for objects with protected members or inheritance
  
  ToNull(a);
}


Альтернатива приветствуется.