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

 
amrali #:

Побитовые операторы преобразуют небольшие целые числа (такие как char/uchar) в знаковые инты. https://stackoverflow. com/a/28142065

Интегральные преобразования небольших целых чисел имеют побочные эффекты, о которых следует знать. В следующем примере значение uchar/char может быть сдвинуто влево больше, чем его ширина (<< больше 8 бит)

Существует также другая проблема с побитовыми операторами(знаковыми типами):

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

Вероятно, лучше избегать побитовых операций с char/uchar или short/ushort.

Зачем вам это вообще нужно?

Если вы хотите использовать биты для представления тиковых данных, просто посчитайте, сколько битов вам нужно, и используйте достаточное количество int (или long ?) для их соответствия. У меня нет времени этим заниматься, но это может быть интересно.

 
fxsaber #:
Такая задача.

Здесь https://www.mql5.com/en/forum/349798/page3#comment_57408237

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

Скрипты: TickCompressor

amrali, 2025.07.04 02:54

TickCompressor v.0.1c: полностью устранена потеря точности при использовании арифметического (int) кодирования тиковых цен с фиксированной точкой.(идея взята у fxsaber)


Scripts: TickCompressor
Scripts: TickCompressor
  • 2025.07.02
  • fxsaber
  • www.mql5.com
Articles, Library comments: Scripts: TickCompressor
Файлы:
 

Попробуйте замерить критерий эффективности ваших правок (взят отсюда).

// Возвращает размер массива в байтах.
template <typename T>
ulong GetSize( const T &Array[] ) { return((ulong)sizeof(T) * ArraySize(Array)); }

// Критерий эффективности работы формата сжатия.
template <typename T1, typename T2>
double Criterion( const T1 &Decompression[], const T2 &Compression[], const ulong Interval )
{
  const double Performance = (double)ArraySize(Decompression) / Interval;
  
  return(Performance * ((double)GetSize(Decompression) / GetSize(Compression)));
}
TicksShort
TicksShort
  • 2025.07.04
  • www.mql5.com
Короткий формат хранения тиков.
 
fxsaber #:
Просьба пояснить с побитовыми операциями.


Почему побитовая операция приводит к созданию int-переменной?

Как дешево делать побитовые операции?


Это правильно?


ЗЫ Перенес в эту ветку, т.к. она autotranslate.

Учим плюсы и улыбаемся)))

https://en.cppreference.com/w/cpp/language/operator_arithmetic.html

Раздел Built-in bitwise shift operators
Там читаем:

  1. Integral promotions are performed on both operands.
  2. In the remaining description in this section, "operand(s)", a, b, lhs and rhs refer to the converted or promoted operand(s).
  3. The type of the result is that of lhs.
 
Vladimir Simakov #:

Учим плюсы и улыбаемся)))

https://en.cppreference.com/w/cpp/language/operator_arithmetic.html

Спасибо. Мне хотелось бы найти быстрый способ умножения int на отрицательную степень 10-ти.

 
fxsaber #:

Спасибо. Мне хотелось бы найти быстрый способ умножения int на отрицательную степень 10-ти.

Это ты, что бы в цикле на 10 не делить? Что-то, что примерно так же работало бы:

С++17:

template<int64_t N, typename = std::enable_if_t<(N < 0)>>
double mult(int i) {
    constexpr double kMult = []() constexpr {
        double ret = 1.0;
        int64_t n = N;
        while (n++ < 0) {
            ret /= 10.0;
        }
        return ret;
    }();
    return i * kMult;
}

int main() {
    auto x = mult<-7>(100);
    std::cout << x << '\n';
}

 
Vladimir Simakov #:

Это ты, что бы в цикле на 10 не делить?

Про это.
TickOut.bid = ::NormalizeDouble((this.PriceBid += ShiftBid) * this.Pow, 7/* this.digits*/);
Если Pow сделать float, то сразу ускорение. Но тогда потеря точности на том же BTCUSD.
 
fxsaber #:
Про это. Если Pow сделать float, то сразу ускорение. Но тогда потеря точности на том же BTCUSD.
OpenCL не пробовали подключать к такому типу задачи(упаковка-распаковка)?

 
Nikolai Semko #:
OpenCL не пробовали подключать к такому типу задачи(упаковка-распаковка)?

Я совсем не в этой теме. Скорость уже неплохая. Но для самообразования было бы интересно посмотреть готовый вариант.

 
#property script_show_inputs

input datetime inFrom = D'2024.12.01';

#include <fxsaber\TicksShort\TicksShort.mqh> // https://www.mql5.com/ru/code/61126
#include <TickCompressor__3.mqh> // https://www.mql5.com/ru/forum/170952/page303#comment_57411774

// Возвращает размер массива в байтах.
template <typename T>
ulong GetSize( const T &Array[] ) { return((ulong)sizeof(T) * ArraySize(Array)); }

template <typename T1, typename T2>
double Criterion( const T1 &Decompression[], const T2 &Compression[], const ulong Interval )
{
  const double Performance = (double)ArraySize(Decompression) / Interval;

  return(Performance * ((double)GetSize(Decompression) / GetSize(Compression)));
}

void OnStart()
{
  MqlTick Ticks[]; // Для исходных тиков.

  if (CopyTicksRange(_Symbol, Ticks, COPY_TICKS_ALL,(ulong)inFrom * 1000) > 0)
  {
//    TICK_SHORT Ticks2[]; // Для сжатых тиков.
    MqlTickBidAsk Ticks2[]; // Для сжатых тиков.

    ulong Interval = GetMicrosecondCount();
//    TICKS_SHORT::Compress(Ticks, Ticks2); // Сжали.
    TickCompressor::compress(Ticks, Ticks2); // Сжали.
    Interval = GetMicrosecondCount() - Interval;
    const double Performance = (double)ArraySize(Ticks) / Interval;

    Print("Compress performance: " + DoubleToString(Performance, 1) + " Ticks (millions)/sec.");
    Print("Compress performance criterion: " + DoubleToString(Criterion(Ticks, Ticks2, Interval), 1));

    MqlTick Ticks3[]; // Для разжатых тиков.

    ulong Interval2 = GetMicrosecondCount();
//    TICKS_SHORT::Decompress(Ticks2, Ticks3); // Разжали.
    TickCompressor::decompress(Ticks2, Ticks3); // Разжали.
    Interval2 = GetMicrosecondCount() - Interval2;
    const double Performance2 = (double)ArraySize(Ticks3) / Interval2;

    Print("Decompress performance: " + DoubleToString((double)ArraySize(Ticks3) / Interval2, 1) + " Ticks (millions)/sec.");
    Print("Decompress performance criterion: " + DoubleToString(Criterion(Ticks3, Ticks2, Interval2), 1));

    Print("Correct = " + (string)TICKS_SHORT::IsEqual(Ticks, Ticks3)); // Сравнили.
  }
}


Результат (BTCUSD).

Compress performance: 106.2 Ticks (millions)/sec.
Compress performance criterion: 354.0
Decompress performance: 28.8 Ticks (millions)/sec.
Decompress performance criterion: 96.0
Correct = false