ant-kline
Version:
对kline.js的自定义修改
1,054 lines (807 loc) • 23.2 kB
JavaScript
export class ExprEnv {
static inst = null;
_ds = null;
_firstIndex = null;
static get () {
return this.inst;
}
static set (env) {
this.inst = env;
}
getDataSource () {
return this._ds;
}
setDataSource (ds) {
return this._ds = ds;
}
getFirstIndex () {
return this._firstIndex;
}
setFirstIndex (n) {
return this._firstIndex = n;
}
}
export class Expr {
constructor () {
this._rid = 0;
}
execute (index) {
}
reserve (rid, count) {
}
clear () {
}
}
export class OpenExpr extends Expr {
execute (index) {
return ExprEnv.get()._ds.getDataAt(index).open;
}
}
export class HighExpr extends Expr {
execute (index) {
return ExprEnv.get()._ds.getDataAt(index).high;
}
}
export class LowExpr extends Expr {
execute (index) {
return ExprEnv.get()._ds.getDataAt(index).low;
}
}
export class CloseExpr extends Expr {
execute (index) {
return ExprEnv.get()._ds.getDataAt(index).close;
}
}
export class TradeExpr extends Expr {
execute (index) {
let result = "";
if (ExprEnv.get()._ds.getDataAt(index).trade) {
for (const item of ExprEnv.get()._ds.getDataAt(index).trade.detail) {
result += `${this.formatTimestamp(item.trade_time)} [${item.trade_type} P:${item.trade_price.toFixed(4)} B:${item.balance.toFixed(4)}] `
}
}
return result ? result : 'None';
}
add0 (m) {
return m < 10 ? '0' + m : m
}
formatTimestamp (timestamps) {
var time = new Date(parseInt(timestamps) * 1000)
var y = time.getFullYear()
var m = time.getMonth() + 1
var d = time.getDate()
var h = time.getHours()
var mm = time.getMinutes()
var s = time.getSeconds()
return y + '/' + this.add0(m) + '/' + this.add0(d) + ' ' + this.add0(h) + ':' + this.add0(mm) + ':' + this.add0(s)
}
}
export class BalanceExpr extends Expr {
execute (index) {
let balance = 0;
if (ExprEnv.get()._ds.getDataAt(index).trade) {
const detail = ExprEnv.get()._ds.getDataAt(index).trade.detail;
balance = detail[ detail.length - 1 ].balance.toFixed(4);
} else {
balance = window.balance;
}
window.balance = balance;
// console.log('balance', balance)
return balance;
}
}
export class AtrExprDetail extends Expr {
execute (index) {
return ExprEnv.get()._ds.getDataAt(index).atr.toFixed(4)
}
}
export class AtrExprRatio extends Expr {
execute (index) {
return (((ExprEnv.get()._ds.getDataAt(index).atr / ExprEnv.get()._ds.getDataAt(index).close)).toFixed(4)) * 100 + '%'
}
}
export class AtrExpr extends Expr {
execute (index) {
return ((ExprEnv.get()._ds.getDataAt(index).atr / ExprEnv.get()._ds.getDataAt(index).close) * 10000).toFixed(4)
}
}
export class AtrExprSecondDetail extends Expr {
execute (index) {
return ExprEnv.get()._ds.getDataAt(index).atr_second.toFixed(4)
}
}
export class AtrExprSecondRatio extends Expr {
execute (index) {
return (((ExprEnv.get()._ds.getDataAt(index).atr_second / ExprEnv.get()._ds.getDataAt(index).close)).toFixed(4)) * 100 + '%'
}
}
export class AtrExprSecond extends Expr {
execute (index) {
return ((ExprEnv.get()._ds.getDataAt(index).atr_second / ExprEnv.get()._ds.getDataAt(index).close) * 10000).toFixed(4)
}
}
export class VolumeExpr extends Expr {
execute (index) {
return ExprEnv.get()._ds.getDataAt(index).volume;
}
}
export class ConstExpr extends Expr {
constructor (v) {
super();
this._value = v;
}
execute (index) {
return this._value;
}
}
export class ParameterExpr extends Expr {
constructor (name, minValue, maxValue, defaultValue) {
super();
this._name = name;
this._minValue = minValue;
this._maxValue = maxValue;
this._value = this._defaultValue = defaultValue;
}
execute (index) {
return this._value;
}
getMinValue () {
return this._minValue;
}
getMaxValue () {
return this._maxValue;
}
getDefaultValue () {
return this._defaultValue;
}
getValue () {
return this._value;
}
setValue (v) {
if (v === 0)
this._value = 0;
else if (v < this._minValue)
this._value = this._minValue;
else if (v > this._maxValue)
this._value = this._maxValue;
else
this._value = v;
}
}
export class OpAExpr extends Expr {
constructor (a) {
super();
this._exprA = a;
};
reserve (rid, count) {
if (this._rid < rid) {
this._rid = rid;
this._exprA.reserve(rid, count);
}
}
clear () {
this._exprA.clear();
}
}
export class OpABExpr extends Expr {
constructor (a, b) {
super();
this._exprA = a;
this._exprB = b;
}
reserve (rid, count) {
if (this._rid < rid) {
this._rid = rid;
this._exprA.reserve(rid, count);
this._exprB.reserve(rid, count);
}
}
clear () {
this._exprA.clear();
this._exprB.clear();
}
}
export class OpABCExpr extends Expr {
constructor (a, b, c) {
super();
this._exprA = a;
this._exprB = b;
this._exprC = c;
}
reserve (rid, count) {
if (this._rid < rid) {
this._rid = rid;
this._exprA.reserve(rid, count);
this._exprB.reserve(rid, count);
this._exprC.reserve(rid, count);
}
}
clear () {
this._exprA.clear();
this._exprB.clear();
this._exprC.clear();
};
}
export class OpABCDExpr extends Expr {
constructor (a, b, c, d) {
super();
this._exprA = a;
this._exprB = b;
this._exprC = c;
this._exprD = d;
}
reserve (rid, count) {
if (this._rid < rid) {
this._rid = rid;
this._exprA.reserve(rid, count);
this._exprB.reserve(rid, count);
this._exprC.reserve(rid, count);
this._exprD.reserve(rid, count);
}
};
clear () {
this._exprA.clear();
this._exprB.clear();
this._exprC.clear();
this._exprD.clear();
}
}
export class NegExpr extends OpAExpr {
constructor (a) {
super(a);
};
execute (index) {
return -(this._exprA.execute(index));
}
}
export class AddExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) + this._exprB.execute(index);
}
}
export class SubExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) - this._exprB.execute(index);
}
}
export class MulExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) * this._exprB.execute(index);
}
}
export class DivExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
let a = this._exprA.execute(index);
let b = this._exprB.execute(index);
if (a === 0)
return a;
if (b === 0)
return (a > 0) ? 1000000 : -1000000;
return a / b;
}
}
export class GtExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) > this._exprB.execute(index) ? 1 : 0;
}
}
export class GeExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) >= this._exprB.execute(index) ? 1 : 0;
}
}
export class LtExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) < this._exprB.execute(index) ? 1 : 0;
}
}
export class LeExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) <= this._exprB.execute(index) ? 1 : 0;
}
}
export class EqExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return this._exprA.execute(index) === this._exprB.execute(index) ? 1 : 0;
}
}
export class MaxExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return Math.max(this._exprA.execute(index), this._exprB.execute(index));
}
}
export class AbsExpr extends OpAExpr {
constructor (a) {
super(a);
}
execute (index) {
return Math.abs(this._exprA.execute(index));
}
}
export class RefExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
if (this._offset === undefined || this._offset < 0) {
this._offset = this._exprB.execute(index);
if (this._offset < 0) {
throw "offset < 0";
}
}
index -= this._offset;
if (index < 0) {
throw "index < 0";
}
let result = this._exprA.execute(index);
if (isNaN(result)) {
throw "NaN";
}
return result;
}
}
export class AndExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return (this._exprA.execute(index) !== 0) && (this._exprB.execute(index) !== 0) ? 1 : 0;
}
}
export class OrExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
}
execute (index) {
return (this._exprA.execute(index) !== 0) || (this._exprB.execute(index) !== 0) ? 1 : 0;
}
}
export class IfExpr extends OpABCExpr {
constructor (a, b, c) {
super(a, b, c);
}
execute (index) {
return this._exprA.execute(index) !== 0 ? this._exprB.execute(index) : this._exprC.execute(index);
}
}
export class AssignExpr extends OpAExpr {
constructor (name, a) {
super(a);
this._name = name;
this._buf = [];
}
getName () {
return this._name;
}
execute (index) {
return this._buf[ index ];
}
assign (index) {
this._buf[ index ] = this._exprA.execute(index);
if (ExprEnv.get()._firstIndex >= 0 && typeof (this._buf[ index ]) === "number") {
if (isNaN(this._buf[ index ]) && !isNaN(this._buf[ index - 1 ])) {
throw this._name + ".assign(" + index + "): NaN";
}
}
}
reserve (rid, count) {
if (this._rid < rid) {
for (let c = count; c > 0; c--) {
this._buf.push(NaN);
}
}
super.reserve(rid, count);
}
clear () {
super.clear();
this._buf = [];
}
}
export class OutputExpr extends AssignExpr {
static outputStyle = {
None : 0,
Line : 1,
VolumeStick : 2,
MACDStick : 3,
SARPoint : 4,
Custom : 5
};
constructor (name, a, style, color) {
super(name, a);
this._style = (style === undefined) ? OutputExpr.outputStyle.Line : style;
this._color = color;
}
getStyle () {
return this._style;
}
getColor () {
return this._color;
}
}
export class RangeOutputExpr extends OutputExpr {
constructor (name, a, style, color) {
super(name, a, style, color);
}
getName () {
return this._name + this._exprA.getRange();
}
}
export class RangeExpr extends OpABExpr {
constructor (a, b) {
super(a, b);
this._range = -1;
this._buf = [];
}
getRange () {
return this._range;
}
initRange () {
this._range = this._exprB.execute(0);
}
execute (index) {
if (this._range < 0) {
this.initRange();
}
let rA = this._buf[ index ].resultA = this._exprA.execute(index);
if (typeof(rA) !== "number") {
return rA;
}
return this._buf[ index ].result = this.calcResult(index, rA);
}
reserve (rid, count) {
if (this._rid < rid) {
for (let c = count; c > 0; c--) {
this._buf.push({resultA : NaN, result : NaN});
}
}
super.reserve(rid, count);
}
clear () {
super.clear();
this._range = -1;
this._buf = [];
}
}
export class HhvExpr extends RangeExpr {
constructor (a, b) {
super(a, b);
}
calcResult (index, resultA) {
if (this._range === 0) {
return NaN;
}
let first = ExprEnv.get()._firstIndex;
if (first < 0) {
return resultA;
}
if (index > first) {
let n = this._range;
let result = resultA;
let start = index - n + 1;
let i = Math.max(first, start);
for (; i < index; i++) {
let p = this._buf[ i ];
if (result < p.resultA) {
result = p.resultA;
}
}
return result;
} else {
return resultA;
}
}
}
export class LlvExpr extends RangeExpr {
constructor (a, b) {
super(a, b);
}
calcResult (index, resultA) {
if (this._range === 0)
return NaN;
let first = ExprEnv.get()._firstIndex;
if (first < 0)
return resultA;
if (index > first) {
let n = this._range;
let result = resultA;
let start = index - n + 1;
let i = Math.max(first, start);
for (; i < index; i++) {
let p = this._buf[ i ];
if (result > p.resultA)
result = p.resultA;
}
return result;
} else {
return resultA;
}
}
}
export class CountExpr extends RangeExpr {
constructor (a, b) {
super(a, b);
}
calcResult (index, resultA) {
if (this._range === 0)
return NaN;
let first = ExprEnv.get()._firstIndex;
if (first < 0)
return 0;
if (index >= first) {
let n = this._range - 1;
if (n > index - first)
n = index - first;
let count = 0;
for (; n >= 0; n--) {
if (this._buf[ index - n ].resultA !== 0.0)
count++;
}
return count;
} else {
return 0;
}
}
}
export class SumExpr extends RangeExpr {
constructor (a, b) {
super(a, b);
}
calcResult (index, resultA) {
let first = ExprEnv.get()._firstIndex;
if (first < 0)
return resultA;
if (index > first) {
let n = this._range;
if (n === 0 || n >= index + 1 - first) {
return this._buf[ index - 1 ].result + resultA;
}
return this._buf[ index - 1 ].result + resultA - this._buf[ index - n ].resultA;
} else {
return resultA;
}
}
}
export class StdExpr extends RangeExpr {
constructor (a, b) {
super(a, b);
}
calcResult (index, resultA) {
if (this._range === 0)
return NaN;
let stdData = this._stdBuf[ index ];
let first = ExprEnv.get()._firstIndex;
if (first < 0) {
stdData.resultMA = resultA;
return 0.0;
}
if (index > first) {
let n = this._range;
if (n >= index + 1 - first) {
n = index + 1 - first;
stdData.resultMA = this._stdBuf[ index - 1 ].resultMA * (1.0 - 1.0 / n) + (resultA / n);
} else {
stdData.resultMA = this._stdBuf[ index - 1 ].resultMA + (resultA - this._buf[ index - n ].resultA) / n;
}
let sum = 0;
for (let i = index - n + 1; i <= index; i++)
sum += Math.pow(this._buf[ i ].resultA - stdData.resultMA, 2);
return Math.sqrt(sum / n);
}
stdData.resultMA = resultA;
return 0.0;
}
reserve (rid, count) {
if (this._rid < rid) {
for (let c = count; c > 0; c--)
this._stdBuf.push({resultMA : NaN});
}
super.reserve(rid, count);
}
clear () {
super.clear();
this._stdBuf = [];
}
}
export class MaExpr extends RangeExpr {
constructor (a, b) {
super(a, b);
}
calcResult (index, resultA) {
if (this._range === 0)
return NaN;
let first = ExprEnv.get()._firstIndex;
if (first < 0)
return resultA;
if (index > first) {
let n = this._range;
if (n >= index + 1 - first) {
n = index + 1 - first;
return this._buf[ index - 1 ].result * (1.0 - 1.0 / n) + (resultA / n);
}
return this._buf[ index - 1 ].result + (resultA - this._buf[ index - n ].resultA) / n;
} else {
return resultA;
}
}
}
export class EmaExpr extends RangeExpr {
constructor (a, b) {
super(a, b);
}
initRange () {
super.initRange();
this._alpha = 2.0 / (this._range + 1);
}
calcResult (index, resultA) {
if (this._range === 0)
return NaN;
let first = ExprEnv.get()._firstIndex;
if (first < 0)
return resultA;
if (index > first) {
let prev = this._buf[ index - 1 ];
return this._alpha * (resultA - prev.result) + prev.result;
}
return resultA;
}
}
export class ExpmemaExpr extends EmaExpr {
constructor (a, b) {
super(a, b);
};
calcResult (index, resultA) {
let first = ExprEnv.get()._firstIndex;
if (first < 0)
return resultA;
if (index > first) {
let n = this._range;
let prev = this._buf[ index - 1 ];
if (n >= index + 1 - first) {
n = index + 1 - first;
return prev.result * (1.0 - 1.0 / n) + (resultA / n);
}
return this._alpha * (resultA - prev.result) + prev.result;
}
return resultA;
}
}
export class SmaExpr extends RangeExpr {
constructor (a, b, c) {
super(a, b);
this._exprC = c;
this._mul = null;
}
initRange () {
super.initRange();
this._mul = this._exprC.execute(0);
}
calcResult (index, resultA) {
if (this._range === 0)
return NaN;
let first = ExprEnv.get()._firstIndex;
if (first < 0)
return resultA;
if (index > first) {
let n = this._range;
if (n > index + 1 - first)
n = index + 1 - first;
return ((n - 1) * this._buf[ index - 1 ].result + resultA * this._mul) / n;
}
return resultA;
}
}
export class SarExpr extends OpABCDExpr {
constructor (a, b, c, d) {
super(a, b, c, d);
this._buf = [];
this._range = -1;
this._min = null;
this._step = null;
this._max = null;
}
execute (index) {
if (this._range < 0) {
this._range = this._exprA.execute(0);
this._min = this._exprB.execute(0) / 100.0;
this._step = this._exprC.execute(0) / 100.0;
this._max = this._exprD.execute(0) / 100.0;
}
let data = this._buf[ index ];
let exprEnv = ExprEnv.get();
let first = exprEnv._firstIndex;
if (first < 0) {
data.longPos = true;
data.sar = exprEnv._ds.getDataAt(index).low;
data.ep = exprEnv._ds.getDataAt(index).high;
data.af = 0.02;
} else {
let high = exprEnv._ds.getDataAt(index).high;
let low = exprEnv._ds.getDataAt(index).low;
let prev = this._buf[ index - 1 ];
data.sar = prev.sar + prev.af * (prev.ep - prev.sar);
if (prev.longPos) {
data.longPos = true;
if (high > prev.ep) {
data.ep = high;
data.af = Math.min(prev.af + this._step, this._max);
} else {
data.ep = prev.ep;
data.af = prev.af;
}
if (data.sar > low) {
data.longPos = false;
let i = index - this._range + 1;
for (i = Math.max(i, first); i < index; i++) {
let h = exprEnv._ds.getDataAt(i).high;
if (high < h) high = h;
}
data.sar = high;
data.ep = low;
data.af = 0.02;
}
} else {
data.longPos = false;
if (low < prev.ep) {
data.ep = low;
data.af = Math.min(prev.af + this._step, this._max);
} else {
data.ep = prev.ep;
data.af = prev.af;
}
if (data.sar < high) {
data.longPos = true;
let i = index - this._range + 1;
for (i = Math.max(i, first); i < index; i++) {
let l = exprEnv._ds.getDataAt(i).low;
if (low > l) low = l;
}
data.sar = low;
data.ep = high;
data.af = 0.02;
}
}
}
return data.sar;
}
reserve (rid, count) {
if (this._rid < rid) {
for (let c = count; c > 0; c--)
this._buf.push({longPos : true, sar : NaN, ep : NaN, af : NaN});
}
super.reserve(rid, count);
}
clear () {
super.clear();
this._range = -1;
}
}