persistable sclass GeometricPriceCells is PriceCells { // cell size in percent settable double cellSizeInPercent; // one of the cell limits settable double basePrice; *(double *cellSizeInPercent) {} *(double *basePrice, double *cellSizeInPercent) {} double ratio() { ret 1+cellSizeInPercent/100; } double toLogScale(double price) { ret log(price, ratio()); } double fromLogScale(double logPrice) { ret pow(ratio(), logPrice); } double logBasePrice() { ret toLogScale(basePrice); } double remainder(double price) { ret frac(toLogScale(price)-logBasePrice()); } // TODO: fix this logic's rounding problems public bool isCellLimit(double price) { ret remainder(price) == 0; } public double nextCellLimit(double price) { double logPrice = toLogScale(price); double r = remainder(price); logPrice += 1-r; ret fromLogScale(logPrice); } public double previousCellLimit(double price) { double logPrice = toLogScale(price); double r = remainder(price); logPrice -= (r == 0 ? 1 : r); ret fromLogScale(logPrice); } public double nCellLimitsDown(double price, int n) { double logPrice = toLogScale(price); logPrice = previousCellLimit(price)-(n-1); ret fromLogScale(logPrice); } public double nCellLimitsUp(double price, int n) { double logPrice = toLogScale(price); logPrice = nextCellLimit(logPrice)+n; ret fromLogScale(logPrice); } }