crypto-backtest
Version:
Backtesting on market data imported from crypto exchange
108 lines • 4.05 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BacktestBase = void 0;
class BacktestBase {
constructor(options) {
this.candles = [];
this.initialBalance = 0;
this.stoplossLevel = 0; // доля от цены открытия, на которую рыночная цена может упасть
this.fee = 0; // доля
this.trades = [];
this.roundtrips = [];
this.maxLosingSeriesLength = 0;
this.maxDrawDown = 0;
this.currencyBalance = 0;
this.assetBalance = 0;
this.stoplossPrice = 0;
Object.assign(this, options);
}
calculateRountrips() {
let roundtrip = null;
let peak = this.initialBalance;
let losingLength = 0;
this.trades.forEach((trade) => {
// если открытого нет, тогда сначала создать
// предполагается что трейды чередуются, открывающий и закрывающий
if (!roundtrip) {
roundtrip = {
begin: trade.time,
openPrice: trade.price,
openAmount: trade.amount + trade.fee,
fee: trade.fee,
};
}
else {
roundtrip.end = trade.time;
roundtrip.closePrice = trade.price;
roundtrip.closeAmount = trade.amount - trade.fee;
roundtrip.fee = roundtrip.fee + trade.fee;
roundtrip.profit = roundtrip.closeAmount - roundtrip.openAmount;
peak = Math.max(peak, roundtrip.closeAmount);
if (roundtrip.profit > 0) {
losingLength = 0;
}
else {
this.maxLosingSeriesLength = Math.max(this.maxLosingSeriesLength, ++losingLength);
this.maxDrawDown = Math.max(this.maxDrawDown, 1 - roundtrip.closeAmount / peak);
}
this.roundtrips.push(roundtrip);
roundtrip = null;
}
});
}
candleHandler(candle, index, candles) {
const { time, close: price } = candle;
// всегда закрывается трейдом или стоп-лосс
if ((index === candles.length - 1 || price < this.stoplossPrice) &&
this.assetBalance > 0) {
this.sell(time, price);
}
else {
const advice = this.advices.find((a) => a.time === time);
if (advice) {
const { side } = advice;
if (side === "buy" && this.currencyBalance > 0) {
this.buy(time, price);
}
else if (side === "sell" && this.assetBalance > 0) {
this.sell(time, price);
}
}
}
}
buy(time, price) {
this.stoplossPrice = price * this.stoplossLevel;
const fee = this.currencyBalance * this.fee;
const amount = this.currencyBalance - fee;
const quantity = amount / price;
const trade = {
time,
side: "buy",
quantity,
price,
amount,
fee,
};
this.currencyBalance = 0;
this.assetBalance = quantity;
this.trades.push(trade);
}
sell(time, price) {
const quantity = this.assetBalance;
const amount = quantity * price;
const fee = amount * this.fee;
const trade = {
time,
side: "sell",
quantity,
price,
amount,
fee,
};
this.assetBalance = 0;
this.currencyBalance = amount - fee;
this.trades.push(trade);
}
}
exports.BacktestBase = BacktestBase;
//# sourceMappingURL=BacktestBase.js.map