-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathindex.ts
110 lines (93 loc) · 2.94 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { PluginInterface, TimeFrame } from '@debut/types';
import { StatsInterface, StatsState } from '@debut/plugin-stats';
export interface ShutdownPluginAPI {
shutdown: Methods;
}
interface Methods {
isShutdown: () => boolean;
}
export interface ShutdownState {
prevOrders: number;
candlesCount: number;
prevProfit: number;
}
const minOrdersInPeriod = 5;
/**
* Плагин выключает бота если тот выдал слишком плохую статистику
* @param candlesPeriod - 840 это 30 дней на м15 свечах
* @param shutdown - функция выключения
*/
export function geneticShutdownPlugin(
interval: TimeFrame,
shutdown?: (stats: StatsState, state: ShutdownState) => boolean,
): PluginInterface {
const state: ShutdownState = {
candlesCount: 0,
prevOrders: 0,
prevProfit: 0,
};
let candlesPeriod: number;
// Расчет свеч на один месяц
switch (interval) {
case '1min':
candlesPeriod = 43200;
break;
case '5min':
candlesPeriod = 8640;
break;
case '15min':
candlesPeriod = 2880;
break;
case '30min':
candlesPeriod = 1440;
break;
case '1h':
candlesPeriod = 720;
break;
case '4h':
candlesPeriod = 180;
break;
default:
throw Error(`unsupported shutdown plugin interval: ${interval}`);
}
let stats: StatsInterface;
let shutdowned = false;
const shutdownFn = shutdown || defaultShutdownFn;
return {
name: 'shutdown',
api: {
isShutdown() {
return shutdowned;
},
},
onInit() {
stats = this.findPlugin<StatsInterface>('stats');
if (!stats) {
throw 'Genetic Shutdown: stats plugin is required!';
}
},
async onAfterCandle() {
state.candlesCount++;
if (state.candlesCount > 200) {
const report = stats.api.getState();
shutdowned = shutdownFn(report, state);
state.candlesCount = 0;
state.prevProfit = ((report.profit - state.prevProfit) / state.prevProfit) * 100;
state.prevOrders = report.long + report.short;
if (shutdowned) {
await this.debut.dispose();
}
}
},
};
}
const defaultShutdownFn = (stats: StatsState, state: ShutdownState) => {
const totalOrders = stats.long + stats.short;
if (!state.prevOrders && totalOrders < minOrdersInPeriod) {
return true;
}
if (state.prevOrders && totalOrders - state.prevOrders < minOrdersInPeriod) {
return true;
}
return stats.relativeDD > 35 || stats.absoluteDD > 35 || stats.potentialDD > 35 || totalOrders === 0;
};