При написании стратегий на JavaScript из-за некоторых проблем самого языка сценариев это часто приводит к проблемам с числовой точностью в вычислениях. Это оказывает определенное влияние на некоторые расчеты и логические суждения в программе. Например, при вычислении 1 - 0.8
или 0.33 * 1.1
данные об ошибках будут рассчитаны:
function main() {
var a = 1 - 0.8
Log(a)
var c = 0.33 * 1.1
Log(c)
}
Так как же решать такие проблемы? Корень проблемы в следующем:
Максимальный прогресс значений с плавающей запятой составляет 17 знаков после запятой, но точность при выполнении операций намного хуже, чем у целых чисел; целые числа преобразуются в десятичные при выполнении операций; и при вычислении десятичных операций в Java и JavaScript оба сначала преобразуют десятичную десятичную в соответствующую двоичную, часть десятичной не может быть полностью преобразована в двоичную, вот первая ошибка. После того, как десятичные числа преобразуются в двоичные, выполняется операция между двоичными числами для получения двоичного результата. Затем преобразуйте двоичный результат в десятичный, где обычно возникает вторая ошибка.
Чтобы решить эту проблему, я искал некоторые решения в Интернете, а также тестировал и использовал следующие решения для решения этой проблемы:
function mathService() { // addition this.add = function(a, b) { var c, d, e; try { c = a.toString().split(".")[1].length; // Get the decimal length of a } catch (f) { c = 0; } try { d = b.toString().split(".")[1].length; // Get the decimal length of b } catch (f) { d = 0; } //Find e first, multiply both a and b by e to convert to integer addition, then divide by e to restore return e = Math.pow(10, Math.max(c, d)), (this.mul(a, e) + this.mul(b, e)) / e; } // multiplication this.mul = function(a, b) { var c = 0, d = a.toString(), // Convert to string e = b.toString(); // ... try { c += d.split(".")[1].length; // c Accumulate the fractional digit length of a } catch (f) {} try { c += e.split(".")[1].length; // c Accumulate the length of decimal places of b } catch (f) {} // Convert to integer multiplication, then divide by 10^c, move decimal point, restore, use integer multiplication without losing accuracy return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c); }
// Subtraction this.sub = function(a, b) { var c, d, e; try { c = a.toString().split(".")[1].length; // Get the decimal length of a } catch (f) { c = 0; } try { d = b.toString().split(".")[1].length; // Get the decimal length of b } catch (f) { d = 0; } // Same as addition return e = Math.pow(10, Math.max(c, d)), (this.mul(a, e) - this.mul(b, e)) / e; }
// Division this.div = function(a, b) { var c, d, e = 0, f = 0; try { e = a.toString().split(".")[1].length; } catch (g) {} try { f = b.toString().split(".")[1].length; } catch (g) {} // Similarly, convert to integer, after operation, restore return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), this.mul(c / d, Math.pow(10, f - e)); } }
function main() { var obj = new mathService() var a = 1 - 0.8 Log(a) var b = obj.sub(1, 0.8) Log(b) var c = 0.33 * 1.1 Log(c) var d = obj.mul(0.33, 1.1) Log(d) }
Принцип состоит в том, чтобы преобразовать два вычисляемых операнда в целые числа, чтобы избежать проблем с точностью. После расчета (по увеличению при переводе в целые числа) результаты расчета восстанавливаются для получения точных результатов.
Таким образом, когда мы хотим, чтобы программа разместила ордер, когда рыночная цена плюс минимальная точность цены, нам не нужно беспокоиться о числовой точности.
function mathService() { .... // Omitted }
function main() { var obj = new mathService() var depth = exchange.GetDepth() exchange.Sell(obj.add(depth.Bids[0].Price, 0.0001), depth.Bids[0].Amount, "Buy 1 order:", depth.Bids[0]) }
Заинтересованные трейдеры могут прочитать код, понять процесс расчета, задавать вопросы, учиться вместе и прогрессировать вместе.