ivanivan_11: мне одному ТС напоминает по манере и всему остальному hrenfx?)) побольше бы таких героев (никакого сарказма,все реально). должен же кто-то пинать сервисдеск и разрабов чем-то помимо -нарисуйте мне тут в терминале стрелочку другого цвета или прилепите кнопку не сюда,а вооон-туда)
Нет, не вам одному.
Но в отличие от прошлых инкарнаций hrenfx, TC(я надеюсь, что это не он) не выходит за рамки приличий и сложившихся здесь правил. И получается вполне такой приличный спарринг. Мы не возражаем (и никогда не возражали против конструктивной критики), так как благодаря упомянутому ТС, нашли и исправили несколько косяков, уточнили документацию (когда косяки не оказались косяками)
Все же хороший индикатор для решения загадок. Заметил, что реал-тайм сформированные значения индикатора и исторические на одном и том же баре не совпадают часто.
В причинах разобраться не смог, как и с предыдущей загадкой. В прошлый раз оказалось дело в баге CopyTicks. Хочется думать, что я ошибся, но, похоже, все же проявляется какой-то слабо заметный баг. Локализовать мне его не получилось. Как будто идет некая особенность работы индикатора и CopyTicks. В Сервисдеске довольно серьезно обсуждались вопросы несинхронизированности CopyTicks и OnCalculate. И вопросы там остались. Поэтому предполагаю, что собака зарыта где-то в этих слабо уловимых особенностях.
Короче, индикатор отлично это показывает. Поэтому поменьше теории, поближе к телу. Все тот же индикатор, но уже с еще более подробными комментариями и с проверкой на баг
// Индикатор в виде гистограммы показывает проторгованный оборот BUY и SELL#property indicator_separate_window#property indicator_buffers2#property indicator_plots2#property indicator_label1 "TurnOver_BUY"#property indicator_type1 DRAW_HISTOGRAM#property indicator_style1 STYLE_SOLID#property indicator_color1 clrYellow#property indicator_label2 "TurnOver_SELL"#property indicator_type2 DRAW_HISTOGRAM#property indicator_style2 STYLE_SOLID#property indicator_color2 clrRedlong LastTime = 0; // time_msc-время последнего тика (самого свежего), полученного из историиint Count = 0; // Количество тиков в последенем запросе, у которых time_msc == LastTimedouble Buffer0[];
double Buffer1[];
// Возвращает свежие тики, пришедшие после предыдущего вызоваint GetFreshTicks( MqlTick &Ticks[], constuint flags = COPY_TICKS_TRADE, constuint count = 100000 )
{
int Res = 0;
MqlTick NewTicks[];
constint NewAmount = CopyTicks(Symbol(), NewTicks, flags, LastTime, count);
if ((NewAmount > 0) && (Count < NewAmount))
{
Res = ArrayCopy(Ticks, NewTicks, 0, Count);
// Взяли крайнее время из текущей истории
LastTime = Ticks[Res - 1].time_msc;
Count = 1;
// Находим (Count) в текущей истории количество тиков со временем LastTimefor (int i = Res - 2; i >= 0; i--)
{
if (Ticks[i].time_msc < LastTime)
break;
Count++;
}
}
return(Res);
}
// Ширина гистограммыvoid SetScale()
{
constint Width = 9 / (1 << (5 - (int)ChartGetInteger(0, CHART_SCALE)));
if (Width != PlotIndexGetInteger(0, PLOT_LINE_WIDTH))
{
PlotIndexSetInteger(0, PLOT_LINE_WIDTH, Width);
PlotIndexSetInteger(1, PLOT_LINE_WIDTH, Width);
ChartRedraw();
}
}
voidOnInit()
{
SetIndexBuffer(0, Buffer0);
SetIndexBuffer(1, Buffer1);
}
voidOnChartEvent( constint id, constlong &lparam, constdouble &dparam, conststring &sparam )
{
if (id == CHARTEVENT_CHART_CHANGE)
SetScale();
}
// Заполняет бар соответствующими ему тикамиvoid SetBarData( constdatetime TimeBar, constMqlTick &Ticks[], int &Pos, double &TurnOverBuy, double &TurnOverSell )
{
constdatetime NextTime = TimeBar + PeriodSeconds();
constint Amount = ArraySize(Ticks);
while (Pos < Amount)
{
constMqlTick Tick = Ticks[Pos];
if (Tick.time >= NextTime)
break;
if ((bool)(Tick.flags & TICK_FLAG_BUY))
TurnOverBuy += (double)Tick.volume;
elseif ((bool)(Tick.flags & TICK_FLAG_SELL))
TurnOverSell -= (double)Tick.volume;
Pos++;
}
return;
}
// Вычисляет, какие должны быть значения буферов для бара со временем TimeFromvoid ControlBarData( constdatetime TimeFrom, double &TurnOverBuy, double &TurnOverSell )
{
MqlTick Ticks[];
CopyTicks(Symbol(), Ticks, COPY_TICKS_TRADE, (ulong)TimeFrom * 1000, 100000);
int i = 0;
SetBarData(TimeFrom, Ticks, i, TurnOverBuy, TurnOverSell);
return;
}
intOnCalculate( constint rates_total,
constint prev_calculated,
constdatetime &time[],
constdouble &open[],
constdouble &high[],
constdouble &low[],
constdouble &close[],
constlong &tick_volume[],
constlong &volume[],
constint &spread[] )
{
if (prev_calculated == 0)
{
// возьмем тики с начала утренней сессии
LastTime = (TimeCurrent() - (TimeCurrent() % (24 * 3600))) * 1000;
Count = 0;
}
// Зануляем новые барыif (rates_total > prev_calculated)
{
ArrayFill(Buffer0, prev_calculated, rates_total - prev_calculated, 0);
ArrayFill(Buffer1, prev_calculated, rates_total - prev_calculated, 0);
}
MqlTick Ticks[];
// Взяли свеженькие тикиconstint Amount = GetFreshTicks(Ticks);
if (Amount > 0)
{
int Pos;
constdatetime LastTime2 = Ticks[0].time - (Ticks[0].time % PeriodSeconds());
// Находим бар (Pos), включающий первый свежий тикfor (Pos = rates_total - 1; Pos >= 0; Pos--)
if (time[Pos] == LastTime2)
break;
if (Pos >= 0)
{
int i = 0;
// Заполняем бары своими тикамиwhile ((Pos < rates_total) && (i < Amount))
{
SetBarData(time[Pos], Ticks, i, Buffer0[Pos], Buffer1[Pos]);
Pos++;
}
// Какой бар справа будет проверяться#define BAR 2// 2 - второй справа (предпоследний)// Этот кусок нужен для проверки правильности посчитанных значений буферов// Если образовался новый бар и в тиковой истории УЖЕ ЕСТЬ соответствущие ему значенияif ((rates_total >= BAR) && (rates_total > prev_calculated) && (Ticks[Amount - 1].time >= time[rates_total - 1]))
{
double Buf0 = 0;
double Buf1 = 0;
// Вычисляем, какие должны быть значения буферов на посчитанных буферах, согласно ПОЛНОСТЬЮ сформированной тиковой истории для них
ControlBarData(time[rates_total - BAR], Buf0, Buf1);
#define TOSTRING(A) " " + #A + " = " + (string)A
// Если есть различия - выводимif ((Buf0 != Buffer0[rates_total - BAR]) || (Buf1 != Buffer1[rates_total - BAR]))
Alert((string)time[rates_total - BAR] + ":" + TOSTRING(Buf0) + TOSTRING(Buf1) + "," +
TOSTRING(Buffer0[rates_total - BAR]) + TOSTRING(Buffer1[rates_total - BAR]));
}
}
}
return(rates_total);
}
Жирным выделил проверку корректности, которая вот так сигналит при проблемах
Все же хороший индикатор для решения загадок. Заметил, что реал-тайм сформированные значения индикатора и исторические на одном и том же баре не совпадают часто.
В причинах разобраться не смог, как и с предыдущей загадкой. В прошлый раз оказалось дело в баге CopyTicks. Хочется думать, что я ошибся, но, похоже, все же проявляется какой-то слабо заметный баг. Локализовать мне его не получилось. Как будто идет некая особенность работы индикатора и CopyTicks. В Сервисдеске довольно серьезно обсуждались вопросы несинхронизированности CopyTicks и OnCalculate. И вопросы там остались. Поэтому предполагаю, что собака зарыта где-то в этих слабо уловимых особенностях.
Короче, индикатор отлично это показывает. Поэтому поменьше теории, поближе к телу. Все тот же индикатор, но уже с еще более подробными комментариями и с проверкой на баг
Жирным выделил проверку корректности, которая вот так сигналит при проблемах
Buf0 и Buf1 - это что должно быть, согласно истории. А BufferN[rates_total-BAR] - это что по итогу посчиталось во время реал-тайма.
Жирным выделил не различия, а совпадения. Они бывают, как для первого, так и для второго буферов.
В общем, запутанно и сумбурно довольно написал. Но исследовал эту загадку, как только мог. До истины не докопался даже близко.
Вроде, CopyTicks работает, как надо (1432) здесь. А баг вылезает почти сразу.
Кому не влом, посмотрите код. Надо разбираться, т.к. подобные баги полезут и в других индикаторах, где задействован CopyTicks.
Надо разбираться, т.к. подобные баги полезут и в других индикаторах, где задействован CopyTicks.
Получилось локализовать один из багов, вызывающий расхождения в индикаторе. Дело снова в CopyTicks.
Оказывается, если собирать тиковую историю по частям, то она может не совпадать с реальной историей. Советник это показывает
#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280long LastTime = 0; // time_msc-время последнего тика (самого свежего), полученного из историиint Count = 0; // Количество тиков в последенем запросе, у которых time_msc == LastTime// Возвращает следующие тики (после предыдущего вызова)int GetFreshTicks( MqlTick &Ticks[], constuint flags = COPY_TICKS_TRADE, constuint count = 100000 )
{
int Res = 0;
MqlTick NewTicks[];
constint NewAmount = CopyTicks(Symbol(), NewTicks, flags, LastTime, count);
if ((NewAmount > 0) && (Count < NewAmount))
{
Res = ArrayCopy(Ticks, NewTicks, 0, Count);
// Взяли крайнее время из текущей истории
LastTime = Ticks[Res - 1].time_msc;
Count = 1;
// Находим (Count) в текущей истории количество тиков со временем LastTimefor (int i = Res - 2; i >= 0; i--)
{
if (Ticks[i].time_msc < LastTime)
break;
Count++;
}
}
return(ArrayResize(Ticks, Res));
}
// Сравнение двух массивовtemplate <typename T>
bool ArrayEqual( const T &Array1[], const T &Array2[] )
{
constint Amount = MathMin(ArraySize(Array1), ArraySize(Array2));
bool Res = (Amount > 0);
if (Res)
for (int i = 0; i < Amount; i++)
if (_R(Array1[i]) != Array2[i]) // https://www.mql5.com/ru/code/16280
{
Res = false;
ExpertRemove();
break;
}
return(Res);
}
voidOnTick()
{
// возьмем тики с начала утренней сессии
Count = 0;
LastTime = (TimeCurrent() - (TimeCurrent() % (24 * 3600))) * 1000;
MqlTick Ticks[]; // История, собранная по частямMqlTick NewTicks[]; // массив для следующей части тиков// Собираем историю по частям while (GetFreshTicks(NewTicks, COPY_TICKS_TRADE, 100000) > 0)
ArrayCopy(Ticks, NewTicks, ArraySize(Ticks));
if (ArraySize(Ticks) > 0)
{
// Взяли ВСЮ историю тиковPrint(CopyTicks(_Symbol, NewTicks, COPY_TICKS_TRADE, Ticks[0].time_msc, 10000000)); // 10000000 - большое число, чтобы все выкачать.// Проверка на совпадение собранной по частям истории с самой историейPrint(ArrayEqual(NewTicks, Ticks) ? "Equal" : "Not Equal");
}
}
Результат
2016.09.3016:02:54.661 Test (Si-12.16,M1) Not Equal
2016.09.3016:02:54.661 Test (Si-12.16,M1) ExpertRemove() function called2016.09.3016:02:54.621 Test (Si-12.16,M1) 3337402016.09.3016:02:54.121 Test (Si-12.16,M1) Equal
2016.09.3016:02:54.071 Test (Si-12.16,M1) 3337362016.09.3016:02:53.791 Test (Si-12.16,M1) Equal
2016.09.3016:02:53.741 Test (Si-12.16,M1) 333723
Этот советник еще показывает слабенький баг. Выяснил, что в собранной по частям истории могут отсутствовать куски, длительностью в несколько минут. Только лаконичное и понятное воспроизведение в виде кода не придумал. А выкладывать сложное - нет смысла, т.к. никто даже смотреть не будет.
В общем, никак не победить баги CopyTicks. И заметьте, советник работает в режиме ленты (COPY_TICKS_TRADE). Т.е. даже с лентой не получается работать.
Получилось локализовать один из багов, вызывающий расхождения в индикаторе. Дело снова в CopyTicks.
А разве кто-то гарантировал, что тики собранные онлайн будут совпадать с историей? История строится по тикам на сервере, а на клиент может успевать приходить меньше. Например, тут кто-то экспериментировал с запуском параллельно нескольких терминалов подключенных к одному счету - результат: увеличенный пропуск тиков на каждом из терминалов.
Stanislav Korotky: А разве кто-то гарантировал, что тики собранные онлайн будут совпадать с историей? История строится по тикам на сервере, а на клиент может успевать приходить меньше. Например, тут кто-то экспериментировал с запуском параллельно нескольких терминалов подключенных к одному счету - результат: увеличенный пропуск тиков на каждом из терминалов.
Они не собираются онлайн, а берутся частями через CopyTicks.
Все же хороший индикатор для решения загадок. Заметил, что реал-тайм сформированные значения индикатора и исторические на одном и том же баре не совпадают часто.
...
Надо разбираться, т.к. подобные баги полезут и в других индикаторах, где задействован CopyTicks.
мне одному ТС напоминает по манере и всему остальному hrenfx?)) побольше бы таких героев (никакого сарказма,все реально). должен же кто-то пинать сервисдеск и разрабов чем-то помимо -нарисуйте мне тут в терминале стрелочку другого цвета или прилепите кнопку не сюда,а вооон-туда)
Нет, не вам одному.
Но в отличие от прошлых инкарнаций hrenfx, TC(я надеюсь, что это не он) не выходит за рамки приличий и сложившихся здесь правил. И получается вполне такой приличный спарринг. Мы не возражаем (и никогда не возражали против конструктивной критики), так как благодаря упомянутому ТС, нашли и исправили несколько косяков, уточнили документацию (когда косяки не оказались косяками)
Можно, конечно, в данном случае переписатьс вариантом from == 0, но это не дело совсем. Надо выправлять CopyTicks. В Сервисдеск снова?
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Альтернативные реализации стандартных функций/подходов
fxsaber, 2016.09.27 20:30
Вариант CopyTicks, который быстрее оригинала иногда на несколько порядков (from > 0)
Билд 1432 - индикатор из первого поста работает без "Загадки".
В копилку биржевых индикаторов.
Все же хороший индикатор для решения загадок. Заметил, что реал-тайм сформированные значения индикатора и исторические на одном и том же баре не совпадают часто.
В причинах разобраться не смог, как и с предыдущей загадкой. В прошлый раз оказалось дело в баге CopyTicks. Хочется думать, что я ошибся, но, похоже, все же проявляется какой-то слабо заметный баг. Локализовать мне его не получилось. Как будто идет некая особенность работы индикатора и CopyTicks. В Сервисдеске довольно серьезно обсуждались вопросы несинхронизированности CopyTicks и OnCalculate. И вопросы там остались. Поэтому предполагаю, что собака зарыта где-то в этих слабо уловимых особенностях.
Короче, индикатор отлично это показывает. Поэтому поменьше теории, поближе к телу. Все тот же индикатор, но уже с еще более подробными комментариями и с проверкой на баг
Жирным выделил проверку корректности, которая вот так сигналит при проблемах
Buf0 и Buf1 - это что должно быть, согласно истории. А BufferN[rates_total-BAR] - это что по итогу посчиталось во время реал-тайма.
Жирным выделил не различия, а совпадения. Они бывают, как для первого, так и для второго буферов.
В общем, запутанно и сумбурно довольно написал. Но исследовал эту загадку, как только мог. До истины не докопался даже близко.
Вроде, CopyTicks работает, как надо (1432) здесь. А баг вылезает почти сразу.
Кому не влом, посмотрите код. Надо разбираться, т.к. подобные баги полезут и в других индикаторах, где задействован CopyTicks.
Все же хороший индикатор для решения загадок. Заметил, что реал-тайм сформированные значения индикатора и исторические на одном и том же баре не совпадают часто.
В причинах разобраться не смог, как и с предыдущей загадкой. В прошлый раз оказалось дело в баге CopyTicks. Хочется думать, что я ошибся, но, похоже, все же проявляется какой-то слабо заметный баг. Локализовать мне его не получилось. Как будто идет некая особенность работы индикатора и CopyTicks. В Сервисдеске довольно серьезно обсуждались вопросы несинхронизированности CopyTicks и OnCalculate. И вопросы там остались. Поэтому предполагаю, что собака зарыта где-то в этих слабо уловимых особенностях.
Короче, индикатор отлично это показывает. Поэтому поменьше теории, поближе к телу. Все тот же индикатор, но уже с еще более подробными комментариями и с проверкой на баг
Жирным выделил проверку корректности, которая вот так сигналит при проблемах
Buf0 и Buf1 - это что должно быть, согласно истории. А BufferN[rates_total-BAR] - это что по итогу посчиталось во время реал-тайма.
Жирным выделил не различия, а совпадения. Они бывают, как для первого, так и для второго буферов.
В общем, запутанно и сумбурно довольно написал. Но исследовал эту загадку, как только мог. До истины не докопался даже близко.
Вроде, CopyTicks работает, как надо (1432) здесь. А баг вылезает почти сразу.
Кому не влом, посмотрите код. Надо разбираться, т.к. подобные баги полезут и в других индикаторах, где задействован CopyTicks.
Надо разбираться, т.к. подобные баги полезут и в других индикаторах, где задействован CopyTicks.
Получилось локализовать один из багов, вызывающий расхождения в индикаторе. Дело снова в CopyTicks.
Оказывается, если собирать тиковую историю по частям, то она может не совпадать с реальной историей. Советник это показывает
Результат
Этот советник еще показывает слабенький баг. Выяснил, что в собранной по частям истории могут отсутствовать куски, длительностью в несколько минут. Только лаконичное и понятное воспроизведение в виде кода не придумал. А выкладывать сложное - нет смысла, т.к. никто даже смотреть не будет.
В общем, никак не победить баги CopyTicks. И заметьте, советник работает в режиме ленты (COPY_TICKS_TRADE). Т.е. даже с лентой не получается работать.
Получилось локализовать один из багов, вызывающий расхождения в индикаторе. Дело снова в CopyTicks.
А разве кто-то гарантировал, что тики собранные онлайн будут совпадать с историей? История строится по тикам на сервере, а на клиент может успевать приходить меньше. Например, тут кто-то экспериментировал с запуском параллельно нескольких терминалов подключенных к одному счету - результат: увеличенный пропуск тиков на каждом из терминалов.
Все же хороший индикатор для решения загадок. Заметил, что реал-тайм сформированные значения индикатора и исторические на одном и том же баре не совпадают часто.
...
Надо разбираться, т.к. подобные баги полезут и в других индикаторах, где задействован CopyTicks.
1434 - проблему не решил.
Оказывается, если собирать тиковую историю по частям, то она может не совпадать с реальной историей. Советник это показывает