fxsaber #: Валидная (за редким исключением) цена - последняя в серии last-цен. Промежуточные никакого отношения к возможному совершению сделок не имеют.
Да, но заранее нельзя определить какой тик последний в серии.
Мой вариант тоже рабочий, просто на несколько тиков больше будет и проверок на SL>=Last. Чуть медленнее тестирование будет, чем с одним самым последним Last.
Если только для сохранения в кастом или для мат. режима, то можно через промежуточный массив сделать и еще 20-50% тиков Last выкинуть. Но я делаю вариант, который и для сохранения годится и на лету будет отклонять ненужные Last тики и в штатной работе тестера они будут отклоняться сразу на входе в OnTick() и тоже давать ускорение.
Сделал такой корректировщик Bid/Ask по Last выбираемым из стакана
Корректирую Bid/Ask только первого тика на новом уровне, а не последнего, так как заранее неизвестно какой тик будет последним и по цене уровня и в серии.
Заодно сделал пропуск Last-ов по одинаковой цене, для стратегий не использующих объемы.
Вызов такой:
Почистил тики с одинаковым Last так как volume не использую, объем файлов для мат. режима с 240 до 107 мб сократился, т.е. будет в 2+ раза быстрее тестироваться. Кастомный символ примерно так же сократится.
Усовершенствовал и еще около 20% тиков выкинул: Добавил в флаги метку Ask или Bid. Часто после тика Ask или Bid следовал первый тик Last с ценой Ask или Bid. В итоге были полные дубликаты по ценам. Их можно пропустить.
bool Correct_last(MqlTick &Tick, bool skip_same_last_){// skip_same_last_ - пропустить тики с той же ценой, если объемы не важны для стратегии, это ускорит работу тестераstaticdouble prev_ask=-1,prev_bid=-1;
if((Tick.flags&TICK_FLAG_LAST)>0){//Last тикif((Tick.flags&TICK_FLAG_SELL)>0){//Last Sell тикif(prev_bid==Tick.last){return skip_same_last_;}//пропустить тики с той же ценой, если skip_same_last_==true
Tick.bid=prev_bid=Tick.last;//корректировать только 1-й тик на уровне
Tick.flags|=TICK_FLAG_BID;
}
elseif((Tick.flags&TICK_FLAG_BUY)>0){//Last Buy тикif(prev_ask==Tick.last){return skip_same_last_;}//пропустить тики с той же ценой, если skip_same_last_==true
Tick.ask=prev_ask=Tick.last;//корректировать только 1-й тик на уровне
Tick.flags|=TICK_FLAG_ASK;
}
}else{// для пропуска первого Last по цене bid или ask, сократит число тиков на 15-20%if((Tick.flags&TICK_FLAG_BID)>0){prev_bid=Tick.bid;}
elseif((Tick.flags&TICK_FLAG_ASK)>0){prev_ask=Tick.ask;}
}
returnfalse;
}
Результат чистки и правки тиков для одной из серий:(нашел большую серию, большинство намного меньше)
Bid менялся от 15 до 11 и в работу уйдет всего 5 тиков вместо 21 Стобцы: time,bid,ask,last,volume,volume dbl,flag
Если только для сохранения в кастом или для мат. режима, то можно через промежуточный массив сделать и еще 20-50% тиков Last выкинуть.
Еще вариант без промежуточного массива: задерживать все тики до изменения миллисекунды, и при наступлении новой, отдавать задержанную с последней ценой и сразу же новую. И заодно объем можно суммировать. Для сохранения тиков в кастом или мат. режим - задержка не критична, а вот на лету может быть...
Еще вариант без промежуточного массива: задерживать все тики до изменения миллисекунды, и при наступлении новой, отдавать задержанную с последней ценой и сразу же новую. И заодно объем можно суммировать. Для сохранения тиков в кастом или мат. режим - задержка не критична, а вот на лету может быть...
Попробую сделать.
Наверно нет смысла к миллисекунде привязываться - пока идут Last-ы их все и задерживать до первого Ask|Bid. Может несколько серий объединит. Но тогда можно просто следующий Ask|Bid использовать, как изначально предлагал.
Aleksei Kuznetsov #: Но тогда можно просто следующий Ask|Bid использовать, как изначально предлагал.
В таком случае, самое простое и правильное решение для MQ:
сделать триггер для SL не по цене Last как сейчас (для которой записан старый Ask|Bid), а просто по Ask|Bid ценам которые придут после нескольких Last (или без них), тогда автоматически применится актуальный Ask|Bid.
Для записи тиков в кастомный символ или для мат. режима - просто пропускать все Last тики, тогда все будет работать по новым актуальным Ask|Bid.
В таком случае, самое простое и правильное решение для MQ:
сделать триггер для SL не по цене Last как сейчас (для которой записан старый Ask|Bid), а просто по Ask|Bid ценам которые придут после нескольких Last (или без них), тогда автоматически применится актуальный Ask|Bid.
Для записи тиков в кастомный символ или для мат. режима - просто пропускать все Last тики, тогда все будет работать по новым актуальным Ask|Bid.
Вот функция такой чистки Last-ов
bool Skip_last(MqlTick &t, bool add_volume){//Пропустит все Last тики, если add_volume=T, то сохранит сумму объемов и последнюю цену из Last в первые после них Ask/Bid тики. Если тик и Ask и Bid, то будет сумма покупок и продаж. Если только Ask или Bid, то по отдельности.staticdouble vB=0,vS=0,lastB=0,lastS=0;
if((t.flags&TICK_FLAG_LAST)>0){//Last тикif(add_volume){//посчитать сумму объемовif((t.flags&TICK_FLAG_SELL)>0){vS+=t.volume_real; lastS=t.last;}//Last Sell тикif((t.flags&TICK_FLAG_BUY )>0){vB+=t.volume_real; lastB=t.last;}//Last Buy тик
}
returntrue;//пропустить Last тик
}else{//Ask/Bid тикif((t.flags&(TICK_FLAG_BID|TICK_FLAG_ASK))>0){t.volume_real=0;t.volume=0;}//сейчас (2026) там объем от предыдущего Lastif(vS>0 && (t.flags&TICK_FLAG_BID)>0){t.volume_real+=vS;t.volume=(ulong)t.volume_real; t.flags|=TICK_FLAG_SELL|TICK_FLAG_VOLUME|TICK_FLAG_LAST; t.last=lastS; vS=0;}
if(vB>0 && (t.flags&TICK_FLAG_ASK)>0){t.volume_real+=vB;t.volume=(ulong)t.volume_real; t.flags|=TICK_FLAG_BUY |TICK_FLAG_VOLUME|TICK_FLAG_LAST; t.last=lastB; vB=0;}
}
returnfalse;//обработать Ask/Bid тик
}
Распчатал туже серию, что и выше Bid тиками до и после, объемы просуммировал и добавил к Ask/Bid, к флагам добавились TICK_FLAG_SELL|TICK_FLAG_VOLUME|TICK_FLAG_LAST
Объем файлов сократился еще сильнее до 63 мб (было с 240мб до 107мб в предыдущей версии с 1 Last на каждом уровне)
В мат. режиме с Virtual положительные проскальзывания из SL исчезли, то что и хотел получить, так как это правильно.
Но появились положительные проскальзывания для лимитных ордеров при открытии позиций. А это думаю, плохо, так как в реальности исполнится точно. То есть для Stop ордеров нужно учитывать Ask/Bid, что я и сделал. А для лимитных нужен свой тригер в Virtual для биржевого исполнения.
Проскальзывания из Virtual в мат режиме с удаленными Last:
MQ тестер показывает такие проскальзывания (все входы по лимиткам с 0 проскальзыванием, кроме одного +200)
Да, тоже уже нашел. Как раз тестирую. Жаль, что дефайнами сделано, а не через переменные. Отдельную версию для бирж надо держать и отдельную для форекса.
Валидная (за редким исключением) цена - последняя в серии last-цен. Промежуточные никакого отношения к возможному совершению сделок не имеют.
Да, но заранее нельзя определить какой тик последний в серии.
Мой вариант тоже рабочий, просто на несколько тиков больше будет и проверок на SL>=Last. Чуть медленнее тестирование будет, чем с одним самым последним Last.
Если только для сохранения в кастом или для мат. режима, то можно через промежуточный массив сделать и еще 20-50% тиков Last выкинуть. Но я делаю вариант, который и для сохранения годится и на лету будет отклонять ненужные Last тики и в штатной работе тестера они будут отклоняться сразу на входе в OnTick() и тоже давать ускорение.
Сделал такой корректировщик Bid/Ask по Last выбираемым из стакана
Корректирую Bid/Ask только первого тика на новом уровне, а не последнего, так как заранее неизвестно какой тик будет последним и по цене уровня и в серии.
Заодно сделал пропуск Last-ов по одинаковой цене, для стратегий не использующих объемы.
Вызов такой:
Почистил тики с одинаковым Last так как volume не использую, объем файлов для мат. режима с 240 до 107 мб сократился, т.е. будет в 2+ раза быстрее тестироваться. Кастомный символ примерно так же сократится.
Добавил в флаги метку Ask или Bid.
Часто после тика Ask или Bid следовал первый тик Last с ценой Ask или Bid. В итоге были полные дубликаты по ценам. Их можно пропустить.
Результат чистки и правки тиков для одной из серий:(нашел большую серию, большинство намного меньше)
Bid менялся от 15 до 11 и в работу уйдет всего 5 тиков вместо 21
Стобцы: time,bid,ask,last,volume,volume dbl,flag
2025.09.04 15:37:50.424 131.15 131.16 131.15 5 5.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.15 75 75.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.15 18 18.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.15 10 10.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 264 264.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 80 80.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 95 95.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 300 300.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 1 1.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 1 1.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 10 10.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 80 80.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 60 60.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 150 150.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 80 80.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 60 60.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 150 150.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 200 200.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 5 5.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 25 25.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 200 200.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 136 136.0 344
2025.09.04 15:37:55.681 131.11 131.16 131.11 136 136.0 2
2025.09.04 15:37:55.680 131.14 131.16 131.14 264 264.0 346
2025.09.04 15:37:55.680 131.13 131.16 131.13 10 10.0 346
2025.09.04 15:37:55.680 131.12 131.16 131.12 80 80.0 346
2025.09.04 15:37:55.680 131.11 131.16 131.11 5 5.0 346
2025.09.04 15:37:55.681 131.11 131.16 131.11 136 136.0 2
Да, но заранее нельзя определить какой тик последний в серии.
MQ в своем Тестере это сделать могут при желании.
Мой вариант тоже рабочий, просто на несколько тиков больше будет и проверок на SL>=Last.
Тогда можно будет совершать сделки по промежуточным ценам, чего в реальности быть не может.
Если только для сохранеия в кастом или для мат режима, то можно через промежуточный массив сделать и еще 20-50% тиков Last выкинуть.
Почти каждая серия last-цен заменятся на один bid/ask. Причем в некоторых случаях нужно делать так.
PrevTick.bid = PrevTick.last - TickSize; // PrevTick.ask = PrevTick.last + TickSize;Т.е. иногда точно можно сказать, что цена даже хуже последнего last в серии.
MQ в своем Тестере это сделать могут при желании.
Могут, будем надеяться что сделают.
Если только для сохранения в кастом или для мат. режима, то можно через промежуточный массив сделать и еще 20-50% тиков Last выкинуть.
Еще вариант без промежуточного массива:
задерживать все тики до изменения миллисекунды, и при наступлении новой, отдавать задержанную с последней ценой и сразу же новую. И заодно объем можно суммировать. Для сохранения тиков в кастом или мат. режим - задержка не критична, а вот на лету может быть...
Попробую сделать.
Могут, будем надеяться...
Еще вариант без промежуточного массива:
задерживать все тики до изменения миллисекунды, и при наступлении новой, отдавать задержанную с последней ценой и сразу же новую. И заодно объем можно суммировать. Для сохранения тиков в кастом или мат. режим - задержка не критична, а вот на лету может быть...
Попробую сделать.
Но тогда можно просто следующий Ask|Bid использовать, как изначально предлагал.
Но тогда можно просто следующий Ask|Bid использовать, как изначально предлагал.
В таком случае, самое простое и правильное решение для MQ:
сделать триггер для SL не по цене Last как сейчас (для которой записан старый Ask|Bid), а просто по Ask|Bid ценам которые придут после нескольких Last (или без них), тогда автоматически применится актуальный Ask|Bid.
Для записи тиков в кастомный символ или для мат. режима - просто пропускать все Last тики, тогда все будет работать по новым актуальным Ask|Bid.В таком случае, самое простое и правильное решение для MQ:
сделать триггер для SL не по цене Last как сейчас (для которой записан старый Ask|Bid), а просто по Ask|Bid ценам которые придут после нескольких Last (или без них), тогда автоматически применится актуальный Ask|Bid.
Для записи тиков в кастомный символ или для мат. режима - просто пропускать все Last тики, тогда все будет работать по новым актуальным Ask|Bid.Вот функция такой чистки Last-ов
Распчатал туже серию, что и выше Bid тиками до и после, объемы просуммировал и добавил к Ask/Bid, к флагам добавились TICK_FLAG_SELL|TICK_FLAG_VOLUME|TICK_FLAG_LAST
Стобцы: time,bid,ask,last,volume,volume dbl,flag
2025.09.04 15:37:50.424 131.15 131.16 131.15 5 5.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.15 75 75.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.15 18 18.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.15 10 10.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 264 264.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 80 80.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 95 95.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 300 300.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 1 1.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.14 1 1.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 10 10.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 80 80.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 60 60.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.13 150 150.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 80 80.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 60 60.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 150 150.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.12 200 200.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 5 5.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 25 25.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 200 200.0 344
2025.09.04 15:37:55.680 131.15 131.16 131.11 136 136.0 344
2025.09.04 15:37:55.681 131.11 131.16 131.11 136 136.0 2
2025.09.04 15:37:55.681 131.11 131.16 131.11 2005 2005.0 90
И если не сохранять объемы, то
2025.09.04 15:37:48.22 131.15 131.16 0.0 0 0.0 0
2025.09.04 15:37:55.681 131.11 131.16 0.0 0 0.0 0
Объем файлов сократился еще сильнее до 63 мб (было с 240мб до 107мб в предыдущей версии с 1 Last на каждом уровне)
В мат. режиме с Virtual положительные проскальзывания из SL исчезли, то что и хотел получить, так как это правильно.
Но появились положительные проскальзывания для лимитных ордеров при открытии позиций. А это думаю, плохо, так как в реальности исполнится точно.
То есть для Stop ордеров нужно учитывать Ask/Bid, что я и сделал. А для лимитных нужен свой тригер в Virtual для биржевого исполнения.
Проскальзывания из Virtual в мат режиме с удаленными Last:
MQ тестер показывает такие проскальзывания (все входы по лимиткам с 0 проскальзыванием, кроме одного +200)
Но появились положительные проскальзывания для лимитных ордеров при открытии позиций. А это думаю, плохо, так как в реальности исполнится точно.
То есть для Stop ордеров нужно учитывать Ask/Bid, что я и сделал. А для лимитных нужен свой тригер в Virtual для биржевого исполнения.
// #define VIRTUAL_LIMITS_TP_SLIPPAGE // Лимитники и TP исполняются по первой цене акцепта - положительные проскальзыванияТак отключите.
Да, тоже уже нашел. Как раз тестирую. Жаль, что дефайнами сделано, а не через переменные. Отдельную версию для бирж надо держать и отдельную для форекса.
Протестировал, теперь как надо:

Вот функция такой чистки Last-ов