Scripts: TickCompressor - page 3

 
void OnStart()
{  
  double BTCUSD = 131072.01; // BTCUSD in future.
  
  Print(NormalizeDouble(BTCUSD, 2));        // 131072.01
  Print(NormalizeDouble((float)BTCUSD, 2)); // 131072.02
}


 
fxsaber #:


This is a float limitation, with 8 digits needed precision, the smallest digit becomes unreliable due to the low accuracy, that is a step between 2 adjacent (distinguished) numbers which can be stored as float-s:

   Print(FLT_EPSILON * 131072.01); // 0.015625001192092897
 
Stanislav Korotky #:
Suggested edits with NormalizeDouble in decompress-es attached.

TickCompressor v.0.1c: totally eliminated loss of precision by using fixed-point arithemtic (int) encoding for tick prices. (idea here from fxsaber)

Round-tripping:

const double _power10[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8};

//MaxPrice = 536870911 / MathPow(10, digits)
//digits = 6, MaxPrice = 536.870911.
//digits = 5, MaxPrice = 5368.70911.
//digits = 4, MaxPrice = 53687.0911.
uint PriceToInteger(const double price, const int digits)
{
  return (uint)(price * _power10[digits] * (1 + DBL_EPSILON)) | (digits << 29);
}

double IntegerToPrice(const uint price)
{
  const uint digits = price >> 29;
  return NormalizeDouble((price & (UINT_MAX >> 3)) / _power10[digits], digits);
}

void OnStart()
{
  // check compression-decompression is round-tripping
  double BTCUSD = 131072.01;
  Print(BTCUSD == IntegerToPrice(PriceToInteger(BTCUSD, 2)));  // true

  double EURUSD = 1.03778;
  Print(EURUSD == IntegerToPrice(PriceToInteger(EURUSD, 5)));  // true

  double ask = 128.00001;
  Print(ask == IntegerToPrice(PriceToInteger(ask, 5)));        // true
}
Files:
 
amrali #:

TickCompressor v.0.1c: totally eliminated loss of precision by using fixed-point arithemtic (int) encoding for tick prices. (idea here from fxsaber)

Thank you for the elaboration.