bfxsentry-agent 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/default.yaml +137 -0
- package/config/phase1-safety.yaml +24 -0
- package/dist/bin/sentry.d.ts +3 -0
- package/dist/bin/sentry.d.ts.map +1 -0
- package/dist/bin/sentry.js +124 -0
- package/dist/bin/sentry.js.map +1 -0
- package/dist/src/backtest/fill-simulator.d.ts +5 -0
- package/dist/src/backtest/fill-simulator.d.ts.map +1 -0
- package/dist/src/backtest/fill-simulator.js +43 -0
- package/dist/src/backtest/fill-simulator.js.map +1 -0
- package/dist/src/backtest/report.d.ts +3 -0
- package/dist/src/backtest/report.d.ts.map +1 -0
- package/dist/src/backtest/report.js +43 -0
- package/dist/src/backtest/report.js.map +1 -0
- package/dist/src/backtest/runner.d.ts +34 -0
- package/dist/src/backtest/runner.d.ts.map +1 -0
- package/dist/src/backtest/runner.js +132 -0
- package/dist/src/backtest/runner.js.map +1 -0
- package/dist/src/collector/basis-monitor.d.ts +9 -0
- package/dist/src/collector/basis-monitor.d.ts.map +1 -0
- package/dist/src/collector/basis-monitor.js +52 -0
- package/dist/src/collector/basis-monitor.js.map +1 -0
- package/dist/src/collector/bitfinex-rest.d.ts +20 -0
- package/dist/src/collector/bitfinex-rest.d.ts.map +1 -0
- package/dist/src/collector/bitfinex-rest.js +350 -0
- package/dist/src/collector/bitfinex-rest.js.map +1 -0
- package/dist/src/collector/event-detector.d.ts +3 -0
- package/dist/src/collector/event-detector.d.ts.map +1 -0
- package/dist/src/collector/event-detector.js +41 -0
- package/dist/src/collector/event-detector.js.map +1 -0
- package/dist/src/collector/polymarket.d.ts +32 -0
- package/dist/src/collector/polymarket.d.ts.map +1 -0
- package/dist/src/collector/polymarket.js +89 -0
- package/dist/src/collector/polymarket.js.map +1 -0
- package/dist/src/collector/types.d.ts +114 -0
- package/dist/src/collector/types.d.ts.map +1 -0
- package/dist/src/collector/types.js +2 -0
- package/dist/src/collector/types.js.map +1 -0
- package/dist/src/core/config.d.ts +67 -0
- package/dist/src/core/config.d.ts.map +1 -0
- package/dist/src/core/config.js +27 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/decision-log.d.ts +7 -0
- package/dist/src/core/decision-log.d.ts.map +1 -0
- package/dist/src/core/decision-log.js +69 -0
- package/dist/src/core/decision-log.js.map +1 -0
- package/dist/src/core/engine.d.ts +19 -0
- package/dist/src/core/engine.d.ts.map +1 -0
- package/dist/src/core/engine.js +148 -0
- package/dist/src/core/engine.js.map +1 -0
- package/dist/src/core/event-bus.d.ts +12 -0
- package/dist/src/core/event-bus.d.ts.map +1 -0
- package/dist/src/core/event-bus.js +21 -0
- package/dist/src/core/event-bus.js.map +1 -0
- package/dist/src/core/logger.d.ts +4 -0
- package/dist/src/core/logger.d.ts.map +1 -0
- package/dist/src/core/logger.js +22 -0
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/core/recorder.d.ts +7 -0
- package/dist/src/core/recorder.d.ts.map +1 -0
- package/dist/src/core/recorder.js +42 -0
- package/dist/src/core/recorder.js.map +1 -0
- package/dist/src/executor/bitfinex-trader.d.ts +3 -0
- package/dist/src/executor/bitfinex-trader.d.ts.map +1 -0
- package/dist/src/executor/bitfinex-trader.js +119 -0
- package/dist/src/executor/bitfinex-trader.js.map +1 -0
- package/dist/src/executor/dry-run.d.ts +4 -0
- package/dist/src/executor/dry-run.d.ts.map +1 -0
- package/dist/src/executor/dry-run.js +39 -0
- package/dist/src/executor/dry-run.js.map +1 -0
- package/dist/src/executor/order-id.d.ts +5 -0
- package/dist/src/executor/order-id.d.ts.map +1 -0
- package/dist/src/executor/order-id.js +20 -0
- package/dist/src/executor/order-id.js.map +1 -0
- package/dist/src/executor/reconciler.d.ts +8 -0
- package/dist/src/executor/reconciler.d.ts.map +1 -0
- package/dist/src/executor/reconciler.js +44 -0
- package/dist/src/executor/reconciler.js.map +1 -0
- package/dist/src/executor/types.d.ts +19 -0
- package/dist/src/executor/types.d.ts.map +1 -0
- package/dist/src/executor/types.js +2 -0
- package/dist/src/executor/types.js.map +1 -0
- package/dist/src/risk/cooldown.d.ts +8 -0
- package/dist/src/risk/cooldown.d.ts.map +1 -0
- package/dist/src/risk/cooldown.js +30 -0
- package/dist/src/risk/cooldown.js.map +1 -0
- package/dist/src/risk/portfolio-filter.d.ts +9 -0
- package/dist/src/risk/portfolio-filter.d.ts.map +1 -0
- package/dist/src/risk/portfolio-filter.js +58 -0
- package/dist/src/risk/portfolio-filter.js.map +1 -0
- package/dist/src/risk/position-manager.d.ts +19 -0
- package/dist/src/risk/position-manager.d.ts.map +1 -0
- package/dist/src/risk/position-manager.js +171 -0
- package/dist/src/risk/position-manager.js.map +1 -0
- package/dist/src/risk/strategy-filter.d.ts +8 -0
- package/dist/src/risk/strategy-filter.d.ts.map +1 -0
- package/dist/src/risk/strategy-filter.js +40 -0
- package/dist/src/risk/strategy-filter.js.map +1 -0
- package/dist/src/risk/var-calculator.d.ts +10 -0
- package/dist/src/risk/var-calculator.d.ts.map +1 -0
- package/dist/src/risk/var-calculator.js +38 -0
- package/dist/src/risk/var-calculator.js.map +1 -0
- package/dist/src/signal/funding-radar.d.ts +4 -0
- package/dist/src/signal/funding-radar.d.ts.map +1 -0
- package/dist/src/signal/funding-radar.js +92 -0
- package/dist/src/signal/funding-radar.js.map +1 -0
- package/dist/src/signal/index.d.ts +12 -0
- package/dist/src/signal/index.d.ts.map +1 -0
- package/dist/src/signal/index.js +37 -0
- package/dist/src/signal/index.js.map +1 -0
- package/dist/src/signal/liquidation.d.ts +4 -0
- package/dist/src/signal/liquidation.d.ts.map +1 -0
- package/dist/src/signal/liquidation.js +83 -0
- package/dist/src/signal/liquidation.js.map +1 -0
- package/dist/src/signal/orderbook.d.ts +4 -0
- package/dist/src/signal/orderbook.d.ts.map +1 -0
- package/dist/src/signal/orderbook.js +100 -0
- package/dist/src/signal/orderbook.js.map +1 -0
- package/dist/src/signal/smart-money.d.ts +4 -0
- package/dist/src/signal/smart-money.d.ts.map +1 -0
- package/dist/src/signal/smart-money.js +39 -0
- package/dist/src/signal/smart-money.js.map +1 -0
- package/dist/src/signal/types.d.ts +13 -0
- package/dist/src/signal/types.d.ts.map +1 -0
- package/dist/src/signal/types.js +2 -0
- package/dist/src/signal/types.js.map +1 -0
- package/dist/src/skill/backtest.d.ts +5 -0
- package/dist/src/skill/backtest.d.ts.map +1 -0
- package/dist/src/skill/backtest.js +14 -0
- package/dist/src/skill/backtest.js.map +1 -0
- package/dist/src/skill/config.d.ts +4 -0
- package/dist/src/skill/config.d.ts.map +1 -0
- package/dist/src/skill/config.js +35 -0
- package/dist/src/skill/config.js.map +1 -0
- package/dist/src/skill/logs.d.ts +5 -0
- package/dist/src/skill/logs.d.ts.map +1 -0
- package/dist/src/skill/logs.js +37 -0
- package/dist/src/skill/logs.js.map +1 -0
- package/dist/src/skill/scan.d.ts +5 -0
- package/dist/src/skill/scan.d.ts.map +1 -0
- package/dist/src/skill/scan.js +75 -0
- package/dist/src/skill/scan.js.map +1 -0
- package/dist/src/skill/signal.d.ts +4 -0
- package/dist/src/skill/signal.d.ts.map +1 -0
- package/dist/src/skill/signal.js +63 -0
- package/dist/src/skill/signal.js.map +1 -0
- package/dist/src/skill/status.d.ts +2 -0
- package/dist/src/skill/status.d.ts.map +1 -0
- package/dist/src/skill/status.js +58 -0
- package/dist/src/skill/status.js.map +1 -0
- package/dist/src/skill/strategy.d.ts +4 -0
- package/dist/src/skill/strategy.d.ts.map +1 -0
- package/dist/src/skill/strategy.js +44 -0
- package/dist/src/skill/strategy.js.map +1 -0
- package/dist/src/skill/trade.d.ts +6 -0
- package/dist/src/skill/trade.d.ts.map +1 -0
- package/dist/src/skill/trade.js +58 -0
- package/dist/src/skill/trade.js.map +1 -0
- package/dist/src/strategy/funding-arb.d.ts +6 -0
- package/dist/src/strategy/funding-arb.d.ts.map +1 -0
- package/dist/src/strategy/funding-arb.js +57 -0
- package/dist/src/strategy/funding-arb.js.map +1 -0
- package/dist/src/strategy/index.d.ts +7 -0
- package/dist/src/strategy/index.d.ts.map +1 -0
- package/dist/src/strategy/index.js +27 -0
- package/dist/src/strategy/index.js.map +1 -0
- package/dist/src/strategy/liq-hunter.d.ts +6 -0
- package/dist/src/strategy/liq-hunter.d.ts.map +1 -0
- package/dist/src/strategy/liq-hunter.js +61 -0
- package/dist/src/strategy/liq-hunter.js.map +1 -0
- package/dist/src/strategy/ob-sniper.d.ts +6 -0
- package/dist/src/strategy/ob-sniper.d.ts.map +1 -0
- package/dist/src/strategy/ob-sniper.js +47 -0
- package/dist/src/strategy/ob-sniper.js.map +1 -0
- package/dist/src/strategy/pm-hedge.d.ts +6 -0
- package/dist/src/strategy/pm-hedge.d.ts.map +1 -0
- package/dist/src/strategy/pm-hedge.js +55 -0
- package/dist/src/strategy/pm-hedge.js.map +1 -0
- package/dist/src/strategy/smart-follow.d.ts +6 -0
- package/dist/src/strategy/smart-follow.d.ts.map +1 -0
- package/dist/src/strategy/smart-follow.js +44 -0
- package/dist/src/strategy/smart-follow.js.map +1 -0
- package/dist/src/strategy/types.d.ts +58 -0
- package/dist/src/strategy/types.d.ts.map +1 -0
- package/dist/src/strategy/types.js +2 -0
- package/dist/src/strategy/types.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# BfxSentry Agent 默认配置
|
|
2
|
+
|
|
3
|
+
engine:
|
|
4
|
+
mode: dry-run # dry-run | live
|
|
5
|
+
log_level: info # debug | info | warn | error
|
|
6
|
+
|
|
7
|
+
collector:
|
|
8
|
+
bitfinex:
|
|
9
|
+
base_url: https://api-pub.bitfinex.com
|
|
10
|
+
symbol: tBTCUSD
|
|
11
|
+
deriv_symbol: tBTCF0:USTF0
|
|
12
|
+
funding_symbol: fUSD
|
|
13
|
+
ws_url: wss://api-pub.bitfinex.com/ws/2
|
|
14
|
+
polymarket:
|
|
15
|
+
gamma_url: https://gamma-api.polymarket.com
|
|
16
|
+
clob_url: https://clob.polymarket.com
|
|
17
|
+
|
|
18
|
+
smart_follow:
|
|
19
|
+
enabled: true
|
|
20
|
+
tick_interval: 180
|
|
21
|
+
entry_conditions:
|
|
22
|
+
min_score: 65
|
|
23
|
+
min_whales_aligned: 5
|
|
24
|
+
min_correlation: 0.5
|
|
25
|
+
position_confirm: true
|
|
26
|
+
exit_conditions:
|
|
27
|
+
score_drop_below: 45
|
|
28
|
+
whale_flip_count: 3
|
|
29
|
+
max_hold_hours: 24
|
|
30
|
+
trailing_stop_pct: 1.5
|
|
31
|
+
risk:
|
|
32
|
+
size_pct: 8
|
|
33
|
+
max_leverage: 2
|
|
34
|
+
stop_loss_pct: 2.0
|
|
35
|
+
|
|
36
|
+
funding_arb:
|
|
37
|
+
enabled: true
|
|
38
|
+
tick_interval: 300
|
|
39
|
+
lend:
|
|
40
|
+
min_rate_percentile: 0.75
|
|
41
|
+
min_utilization: 0.80
|
|
42
|
+
min_spare_capacity: 0.15
|
|
43
|
+
lend_amount_pct: 25
|
|
44
|
+
preferred_period_days: 7
|
|
45
|
+
high_rate_period_days: 30
|
|
46
|
+
high_rate_threshold: 0.90
|
|
47
|
+
warning:
|
|
48
|
+
rate_spike_pct: 5
|
|
49
|
+
critical_utilization: 0.90
|
|
50
|
+
exit_conditions:
|
|
51
|
+
rate_drop_percentile: 0.30
|
|
52
|
+
supply_recovery_pct: 2
|
|
53
|
+
|
|
54
|
+
liq_hunter:
|
|
55
|
+
enabled: true
|
|
56
|
+
tick_interval: 5
|
|
57
|
+
trend_follow:
|
|
58
|
+
min_intensity_pct: 0.85
|
|
59
|
+
min_dominance: 0.70
|
|
60
|
+
min_price_move_pct: 0.3
|
|
61
|
+
price_window_sec: 180
|
|
62
|
+
reversal:
|
|
63
|
+
min_intensity_pct: 0.95
|
|
64
|
+
price_stall_pct: 0.1
|
|
65
|
+
require_ob_confirm: true
|
|
66
|
+
ob_imbalance_threshold: 1.2
|
|
67
|
+
risk:
|
|
68
|
+
size_pct: 5
|
|
69
|
+
max_leverage: 3
|
|
70
|
+
trend_stop_pct: 0.5
|
|
71
|
+
reversal_stop_pct: 0.3
|
|
72
|
+
take_profit_pct: 1.0
|
|
73
|
+
cooldown_sec: 300
|
|
74
|
+
|
|
75
|
+
ob_sniper:
|
|
76
|
+
enabled: true
|
|
77
|
+
tick_interval: 5
|
|
78
|
+
entry_conditions:
|
|
79
|
+
imbalance_buy: 1.5
|
|
80
|
+
imbalance_sell: 0.67
|
|
81
|
+
depth_range_pct: 0.5
|
|
82
|
+
require_flow_confirm: true
|
|
83
|
+
flow_buy_ratio: 0.60
|
|
84
|
+
flow_sell_ratio: 0.40
|
|
85
|
+
flow_window_sec: 60
|
|
86
|
+
wall_multiplier: 5
|
|
87
|
+
wall_break_price_pct: 0.1
|
|
88
|
+
risk:
|
|
89
|
+
size_pct: 5
|
|
90
|
+
max_leverage: 3
|
|
91
|
+
stop_loss_pct: 0.3
|
|
92
|
+
take_profit_pct: 0.5
|
|
93
|
+
signal_ttl_sec: 120
|
|
94
|
+
cooldown_sec: 120
|
|
95
|
+
|
|
96
|
+
pm_hedge:
|
|
97
|
+
enabled: true
|
|
98
|
+
tick_interval: 15
|
|
99
|
+
signal_driven:
|
|
100
|
+
min_confidence: 20
|
|
101
|
+
min_edge_pct: 3
|
|
102
|
+
stake_usdc: 100
|
|
103
|
+
market_making:
|
|
104
|
+
min_spread_cents: 2
|
|
105
|
+
max_inventory_imbalance: 0.3
|
|
106
|
+
hedge_when_imbalance: 0.2
|
|
107
|
+
hedge:
|
|
108
|
+
delta: 0.5
|
|
109
|
+
bfx_instrument: tBTCF0:USTF0
|
|
110
|
+
max_bfx_position_btc: 0.1
|
|
111
|
+
|
|
112
|
+
risk:
|
|
113
|
+
max_total_position_usd: 5000
|
|
114
|
+
max_daily_loss_usd: 200
|
|
115
|
+
max_daily_trades: 50
|
|
116
|
+
max_concurrent_positions: 3
|
|
117
|
+
conflict_resolution: conservative
|
|
118
|
+
same_direction_cooldown_sec: 300
|
|
119
|
+
opposite_signal_cooldown_sec: 60
|
|
120
|
+
max_slippage_pct: 0.1
|
|
121
|
+
order_type: limit
|
|
122
|
+
limit_offset_pct: 0.02
|
|
123
|
+
portfolio:
|
|
124
|
+
max_portfolio_var_pct: 3
|
|
125
|
+
var_confidence: 0.95
|
|
126
|
+
max_same_direction_pct: 70
|
|
127
|
+
circuit_breaker:
|
|
128
|
+
consecutive_losses: 5
|
|
129
|
+
loss_streak_usd: 300
|
|
130
|
+
cooldown_minutes: 60
|
|
131
|
+
action: pause_all
|
|
132
|
+
trading_hours:
|
|
133
|
+
enabled: false
|
|
134
|
+
|
|
135
|
+
recorder:
|
|
136
|
+
enabled: true
|
|
137
|
+
retention_days: 30
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Phase 1 安全覆盖 (前 2 周实盘)
|
|
2
|
+
# 使用: sentry start --mode live --config config/phase1-safety.yaml
|
|
3
|
+
|
|
4
|
+
risk:
|
|
5
|
+
max_total_position_usd: 2000
|
|
6
|
+
max_daily_trades: 15
|
|
7
|
+
max_concurrent_positions: 1
|
|
8
|
+
portfolio:
|
|
9
|
+
circuit_breaker:
|
|
10
|
+
consecutive_losses: 3
|
|
11
|
+
cooldown_minutes: 120
|
|
12
|
+
|
|
13
|
+
smart_follow:
|
|
14
|
+
entry_conditions:
|
|
15
|
+
min_score: 70
|
|
16
|
+
risk:
|
|
17
|
+
size_pct: 5
|
|
18
|
+
|
|
19
|
+
liq_hunter:
|
|
20
|
+
risk:
|
|
21
|
+
size_pct: 3
|
|
22
|
+
|
|
23
|
+
pm_hedge:
|
|
24
|
+
enabled: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry.d.ts","sourceRoot":"","sources":["../../bin/sentry.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { initLogger } from '../src/core/logger.js';
|
|
4
|
+
import { loadConfig } from '../src/core/config.js';
|
|
5
|
+
import { startEngine, stopEngine } from '../src/core/engine.js';
|
|
6
|
+
import { scanCommand } from '../src/skill/scan.js';
|
|
7
|
+
import { signalCommand } from '../src/skill/signal.js';
|
|
8
|
+
import { strategyCommand } from '../src/skill/strategy.js';
|
|
9
|
+
import { positionCommand } from '../src/skill/status.js';
|
|
10
|
+
import { tradeCommand } from '../src/skill/trade.js';
|
|
11
|
+
import { backtestCommand } from '../src/skill/backtest.js';
|
|
12
|
+
import { configCommand } from '../src/skill/config.js';
|
|
13
|
+
import { logsCommand } from '../src/skill/logs.js';
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name('sentry')
|
|
17
|
+
.description('BfxSentry Agent CLI — Bitfinex 信号驱动交易代理')
|
|
18
|
+
.version('0.1.0');
|
|
19
|
+
// ── sentry scan ──
|
|
20
|
+
program
|
|
21
|
+
.command('scan')
|
|
22
|
+
.description('全市场一次性扫描, 不交易')
|
|
23
|
+
.option('--json', 'JSON 输出')
|
|
24
|
+
.option('-c, --config <path>', '自定义配置文件')
|
|
25
|
+
.action(async (options) => {
|
|
26
|
+
initLogger('silent');
|
|
27
|
+
await scanCommand(options);
|
|
28
|
+
});
|
|
29
|
+
// ── sentry signal ──
|
|
30
|
+
program
|
|
31
|
+
.command('signal [module]')
|
|
32
|
+
.description('查看信号详情 (smart-money|funding|liquidation|orderbook|polymarket)')
|
|
33
|
+
.option('-c, --config <path>', '自定义配置文件')
|
|
34
|
+
.action(async (module, options) => {
|
|
35
|
+
initLogger('silent');
|
|
36
|
+
await signalCommand(module, options);
|
|
37
|
+
});
|
|
38
|
+
// ── sentry strategy ──
|
|
39
|
+
program
|
|
40
|
+
.command('strategy [name]')
|
|
41
|
+
.description('查看策略状态 (smart-follow|funding-arb|liq-hunter|ob-sniper|pm-hedge)')
|
|
42
|
+
.option('-c, --config <path>', '自定义配置文件')
|
|
43
|
+
.action(async (name, options) => {
|
|
44
|
+
initLogger('silent');
|
|
45
|
+
await strategyCommand(name, options);
|
|
46
|
+
});
|
|
47
|
+
// ── sentry position ──
|
|
48
|
+
program
|
|
49
|
+
.command('position [action] [id]')
|
|
50
|
+
.description('持仓管理 (close <id> | close-all)')
|
|
51
|
+
.action(async (action, id) => {
|
|
52
|
+
initLogger('silent');
|
|
53
|
+
await positionCommand(action, id);
|
|
54
|
+
});
|
|
55
|
+
// ── sentry trade ──
|
|
56
|
+
program
|
|
57
|
+
.command('trade <direction> <size>')
|
|
58
|
+
.description('手动交易 (long|short <btc_size> [--stop 2%] [--tp 3%])')
|
|
59
|
+
.option('--stop <pct>', '止损百分比', '2%')
|
|
60
|
+
.option('--tp <pct>', '止盈百分比', '3%')
|
|
61
|
+
.option('-c, --config <path>', '自定义配置文件')
|
|
62
|
+
.action(async (direction, size, options) => {
|
|
63
|
+
initLogger('silent');
|
|
64
|
+
await tradeCommand(direction, size, options);
|
|
65
|
+
});
|
|
66
|
+
// ── sentry backtest ──
|
|
67
|
+
program
|
|
68
|
+
.command('backtest [strategy]')
|
|
69
|
+
.description('回测策略 (liq-hunter|smart-follow|ob-sniper|funding-arb|pm-hedge)')
|
|
70
|
+
.option('-d, --days <n>', '回测天数', '7')
|
|
71
|
+
.option('-c, --config <path>', '自定义配置文件')
|
|
72
|
+
.action(async (strategy, options) => {
|
|
73
|
+
initLogger('silent');
|
|
74
|
+
await backtestCommand(strategy, options);
|
|
75
|
+
});
|
|
76
|
+
// ── sentry config ──
|
|
77
|
+
program
|
|
78
|
+
.command('config <action> [args...]')
|
|
79
|
+
.description('配置管理 (show | set <path> <value>)')
|
|
80
|
+
.option('-c, --config <path>', '自定义配置文件')
|
|
81
|
+
.action(async (action, args, options) => {
|
|
82
|
+
initLogger('silent');
|
|
83
|
+
await configCommand(action, args, options);
|
|
84
|
+
});
|
|
85
|
+
// ── sentry logs ──
|
|
86
|
+
program
|
|
87
|
+
.command('logs')
|
|
88
|
+
.description('查看交易日志')
|
|
89
|
+
.option('-l, --level <level>', '日志级别 (all|warn)', 'all')
|
|
90
|
+
.option('-n, --limit <n>', '显示条数', '20')
|
|
91
|
+
.action(async (options) => {
|
|
92
|
+
initLogger('silent');
|
|
93
|
+
await logsCommand(options);
|
|
94
|
+
});
|
|
95
|
+
// ── sentry start ──
|
|
96
|
+
program
|
|
97
|
+
.command('start')
|
|
98
|
+
.description('启动 Agent (持续运行)')
|
|
99
|
+
.option('-m, --mode <mode>', '运行模式 (dry-run|live)', 'dry-run')
|
|
100
|
+
.option('-c, --config <path>', '自定义配置文件')
|
|
101
|
+
.option('-i, --interval <sec>', 'Tick 间隔 (秒)', '10')
|
|
102
|
+
.action(async (options) => {
|
|
103
|
+
const cfg = loadConfig(options.config);
|
|
104
|
+
cfg.engine.mode = options.mode;
|
|
105
|
+
initLogger(cfg.engine.log_level);
|
|
106
|
+
console.log(`\n BfxSentry Agent 启动中... (${cfg.engine.mode} 模式)\n`);
|
|
107
|
+
const shutdown = () => {
|
|
108
|
+
console.log('\n 正在停止...');
|
|
109
|
+
stopEngine();
|
|
110
|
+
setTimeout(() => process.exit(0), 1000);
|
|
111
|
+
};
|
|
112
|
+
process.on('SIGINT', shutdown);
|
|
113
|
+
process.on('SIGTERM', shutdown);
|
|
114
|
+
await startEngine(cfg, parseInt(options.interval));
|
|
115
|
+
});
|
|
116
|
+
// ── sentry stop ──
|
|
117
|
+
program
|
|
118
|
+
.command('stop')
|
|
119
|
+
.description('停止 Agent')
|
|
120
|
+
.action(() => {
|
|
121
|
+
stopEngine();
|
|
122
|
+
});
|
|
123
|
+
program.parse();
|
|
124
|
+
//# sourceMappingURL=sentry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry.js","sourceRoot":"","sources":["../../bin/sentry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TradeIntent, ExecutionResult } from '../strategy/types.js';
|
|
2
|
+
import type { MarketSnapshot } from '../collector/types.js';
|
|
3
|
+
export declare function simulateFill(intent: TradeIntent, snapshot: MarketSnapshot): ExecutionResult;
|
|
4
|
+
export declare function wouldFillLimit(price: number, direction: 'long' | 'short', nextSnapshot: MarketSnapshot): boolean;
|
|
5
|
+
//# sourceMappingURL=fill-simulator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fill-simulator.d.ts","sourceRoot":"","sources":["../../../src/backtest/fill-simulator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAG3D,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,eAAe,CAgC3F;AAGD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAAG,OAAO,EAC3B,YAAY,EAAE,cAAc,GAC3B,OAAO,CAQT"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Simulates order fills conservatively using recorded snapshot data
|
|
2
|
+
export function simulateFill(intent, snapshot) {
|
|
3
|
+
const { ticker, orderbook } = snapshot;
|
|
4
|
+
// Market order: fill at best bid/ask with slippage
|
|
5
|
+
const bestBid = orderbook.bids[0]?.price || ticker.lastPrice;
|
|
6
|
+
const bestAsk = orderbook.asks[0]?.price || ticker.lastPrice;
|
|
7
|
+
let fillPrice;
|
|
8
|
+
if (intent.direction === 'long') {
|
|
9
|
+
// Buying: fill at ask + estimated slippage from depth
|
|
10
|
+
const depth = orderbook.askDepth02;
|
|
11
|
+
const slippage = depth > 0 ? Math.min(0.001, 0.01 / depth) : 0.001;
|
|
12
|
+
fillPrice = bestAsk * (1 + slippage);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
// Selling: fill at bid - estimated slippage
|
|
16
|
+
const depth = orderbook.bidDepth02;
|
|
17
|
+
const slippage = depth > 0 ? Math.min(0.001, 0.01 / depth) : 0.001;
|
|
18
|
+
fillPrice = bestBid * (1 - slippage);
|
|
19
|
+
}
|
|
20
|
+
const capitalUsd = 5000;
|
|
21
|
+
const sizeUsd = capitalUsd * (intent.sizePct / 100);
|
|
22
|
+
const fillSize = sizeUsd / fillPrice;
|
|
23
|
+
return {
|
|
24
|
+
success: true,
|
|
25
|
+
orderId: `bt-${intent.id}`,
|
|
26
|
+
fillPrice,
|
|
27
|
+
fillSize,
|
|
28
|
+
fee: sizeUsd * 0.001,
|
|
29
|
+
timestamp: snapshot.timestamp,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Check if a limit order would have been filled
|
|
33
|
+
export function wouldFillLimit(price, direction, nextSnapshot) {
|
|
34
|
+
if (direction === 'long') {
|
|
35
|
+
// Buy limit fills when ask drops to or below price
|
|
36
|
+
return nextSnapshot.ticker.low <= price;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Sell limit fills when bid rises to or above price
|
|
40
|
+
return nextSnapshot.ticker.high >= price;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=fill-simulator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fill-simulator.js","sourceRoot":"","sources":["../../../src/backtest/fill-simulator.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,QAAwB;IACxE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAA;IAEtC,mDAAmD;IACnD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC,SAAS,CAAA;IAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC,SAAS,CAAA;IAE5D,IAAI,SAAiB,CAAA;IACrB,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,sDAAsD;QACtD,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAA;QAClC,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAClE,SAAS,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAA;IACtC,CAAC;SAAM,CAAC;QACN,4CAA4C;QAC5C,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAA;QAClC,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAClE,SAAS,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAA;IACtC,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAA;IACvB,MAAM,OAAO,GAAG,UAAU,GAAG,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,CAAA;IACnD,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;IAEpC,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,MAAM,MAAM,CAAC,EAAE,EAAE;QAC1B,SAAS;QACT,QAAQ;QACR,GAAG,EAAE,OAAO,GAAG,KAAK;QACpB,SAAS,EAAE,QAAQ,CAAC,SAAS;KAC9B,CAAA;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,SAA2B,EAC3B,YAA4B;IAE5B,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,mDAAmD;QACnD,OAAO,YAAY,CAAC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAA;IACzC,CAAC;SAAM,CAAC;QACN,oDAAoD;QACpD,OAAO,YAAY,CAAC,MAAM,CAAC,IAAI,IAAI,KAAK,CAAA;IAC1C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/backtest/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,QA+CzD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export function printBacktestReport(result) {
|
|
3
|
+
const { summary, period, trades } = result;
|
|
4
|
+
console.log('');
|
|
5
|
+
console.log(chalk.bold.cyan('═══════════════════════════════════════════════════'));
|
|
6
|
+
console.log(chalk.bold.cyan(' BfxSentry · 回测报告'));
|
|
7
|
+
console.log(chalk.bold.cyan('═══════════════════════════════════════════════════'));
|
|
8
|
+
console.log('');
|
|
9
|
+
console.log(` 策略: ${chalk.bold(result.strategy)}`);
|
|
10
|
+
console.log(` 区间: ${new Date(period.start).toLocaleDateString()} — ${new Date(period.end).toLocaleDateString()} (${period.days} 天)`);
|
|
11
|
+
console.log(` 快照数: ${result.snapshotsUsed}`);
|
|
12
|
+
console.log('');
|
|
13
|
+
console.log(chalk.bold(' ── 绩效概览 ──'));
|
|
14
|
+
console.log('');
|
|
15
|
+
const pnlColor = summary.totalPnl >= 0 ? chalk.green : chalk.red;
|
|
16
|
+
console.log(` 总交易: ${summary.totalTrades}`);
|
|
17
|
+
console.log(` 胜/负: ${chalk.green(String(summary.wins))} / ${chalk.red(String(summary.losses))}`);
|
|
18
|
+
console.log(` 胜率: ${(summary.winRate * 100).toFixed(1)}%`);
|
|
19
|
+
console.log(` 总 PnL: ${pnlColor('$' + summary.totalPnl.toFixed(2))}`);
|
|
20
|
+
console.log(` 均 PnL: $${summary.avgPnl.toFixed(2)}`);
|
|
21
|
+
console.log(` 最大回撤: ${(summary.maxDrawdown * 100).toFixed(2)}%`);
|
|
22
|
+
console.log(` Sharpe: ${summary.sharpeRatio.toFixed(2)}`);
|
|
23
|
+
console.log('');
|
|
24
|
+
if (trades.length > 0) {
|
|
25
|
+
console.log(chalk.bold(' ── 最近交易 ──'));
|
|
26
|
+
console.log('');
|
|
27
|
+
console.log(chalk.dim(' 时间 策略 方向 入场 出场 PnL'));
|
|
28
|
+
console.log(chalk.dim(' ─────────────────────────────────────────────────────────────────────'));
|
|
29
|
+
const recent = trades.slice(-15);
|
|
30
|
+
for (const t of recent) {
|
|
31
|
+
const dir = t.direction === 'long' ? chalk.green('多') : chalk.red('空');
|
|
32
|
+
const pnl = t.pnl >= 0 ? chalk.green(`+$${t.pnl.toFixed(2)}`) : chalk.red(`-$${Math.abs(t.pnl).toFixed(2)}`);
|
|
33
|
+
const time = new Date(t.timestamp).toLocaleString().padEnd(20);
|
|
34
|
+
console.log(` ${time} ${t.strategy.padEnd(14)} ${dir} $${t.entryPrice.toFixed(0).padEnd(10)} $${t.exitPrice.toFixed(0).padEnd(10)} ${pnl}`);
|
|
35
|
+
}
|
|
36
|
+
console.log('');
|
|
37
|
+
}
|
|
38
|
+
if (trades.length === 0) {
|
|
39
|
+
console.log(chalk.yellow(' 没有录制数据可供回测。先运行 sentry start 采集数据。'));
|
|
40
|
+
console.log('');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/backtest/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AgentConfig } from '../core/config.js';
|
|
2
|
+
export interface BacktestResult {
|
|
3
|
+
strategy: string | 'all';
|
|
4
|
+
period: {
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
days: number;
|
|
8
|
+
};
|
|
9
|
+
snapshotsUsed: number;
|
|
10
|
+
trades: BacktestTrade[];
|
|
11
|
+
summary: {
|
|
12
|
+
totalTrades: number;
|
|
13
|
+
wins: number;
|
|
14
|
+
losses: number;
|
|
15
|
+
winRate: number;
|
|
16
|
+
totalPnl: number;
|
|
17
|
+
avgPnl: number;
|
|
18
|
+
maxDrawdown: number;
|
|
19
|
+
sharpeRatio: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
interface BacktestTrade {
|
|
23
|
+
timestamp: number;
|
|
24
|
+
strategy: string;
|
|
25
|
+
direction: 'long' | 'short';
|
|
26
|
+
entryPrice: number;
|
|
27
|
+
exitPrice: number;
|
|
28
|
+
pnl: number;
|
|
29
|
+
holdingMs: number;
|
|
30
|
+
reason: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function runBacktest(config: AgentConfig, strategyFilter_: string | undefined, days: number): Promise<BacktestResult>;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/backtest/runner.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAMpD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAA;IACxB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACpD,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAA;QACnB,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,WAAW,EAAE,MAAM,CAAA;QACnB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;CACF;AAED,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,CAAC,CAwHzB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { generateAllSignals } from '../signal/index.js';
|
|
4
|
+
import { evaluateAllStrategies } from '../strategy/index.js';
|
|
5
|
+
import { strategyFilter } from '../risk/strategy-filter.js';
|
|
6
|
+
import { portfolioFilter } from '../risk/portfolio-filter.js';
|
|
7
|
+
import { simulateFill } from './fill-simulator.js';
|
|
8
|
+
import { openPosition, closePosition, checkStopLossAndTakeProfit, updatePositionPrices, getPositions } from '../risk/position-manager.js';
|
|
9
|
+
const DB_PATH = resolve(import.meta.dirname, '..', '..', 'data', 'sentry.db');
|
|
10
|
+
export async function runBacktest(config, strategyFilter_, days) {
|
|
11
|
+
const db = new Database(DB_PATH, { readonly: true });
|
|
12
|
+
const cutoff = Date.now() - days * 86400_000;
|
|
13
|
+
const rows = db.prepare(`
|
|
14
|
+
SELECT data_json, signals_json, timestamp FROM snapshots
|
|
15
|
+
WHERE timestamp >= ? ORDER BY timestamp ASC
|
|
16
|
+
`).all(cutoff);
|
|
17
|
+
db.close();
|
|
18
|
+
if (rows.length === 0) {
|
|
19
|
+
return emptyResult(strategyFilter_ || 'all', days);
|
|
20
|
+
}
|
|
21
|
+
const trades = [];
|
|
22
|
+
let equity = 5000;
|
|
23
|
+
let peakEquity = equity;
|
|
24
|
+
let maxDrawdown = 0;
|
|
25
|
+
const returns = [];
|
|
26
|
+
for (let i = 0; i < rows.length; i++) {
|
|
27
|
+
const snapshot = JSON.parse(rows[i].data_json);
|
|
28
|
+
const price = snapshot.ticker.lastPrice;
|
|
29
|
+
// Update positions
|
|
30
|
+
updatePositionPrices(price);
|
|
31
|
+
// Check stop loss / take profit
|
|
32
|
+
const closed = checkStopLossAndTakeProfit(price);
|
|
33
|
+
for (const c of closed) {
|
|
34
|
+
const pos = getPositions().find(p => p.id === c.posId);
|
|
35
|
+
trades.push({
|
|
36
|
+
timestamp: snapshot.timestamp,
|
|
37
|
+
strategy: pos?.strategy || 'unknown',
|
|
38
|
+
direction: pos?.direction || 'long',
|
|
39
|
+
entryPrice: pos?.entryPrice || 0,
|
|
40
|
+
exitPrice: price,
|
|
41
|
+
pnl: c.pnl,
|
|
42
|
+
holdingMs: pos ? snapshot.timestamp - pos.openedAt : 0,
|
|
43
|
+
reason: c.reason,
|
|
44
|
+
});
|
|
45
|
+
equity += c.pnl;
|
|
46
|
+
returns.push(c.pnl / equity);
|
|
47
|
+
}
|
|
48
|
+
// Generate signals and evaluate strategies
|
|
49
|
+
const signals = generateAllSignals(snapshot);
|
|
50
|
+
let intents = evaluateAllStrategies(signals, snapshot, config);
|
|
51
|
+
if (strategyFilter_) {
|
|
52
|
+
intents = intents.filter(i => i.strategy === strategyFilter_);
|
|
53
|
+
}
|
|
54
|
+
// Risk filter + execute
|
|
55
|
+
for (const intent of intents) {
|
|
56
|
+
const sf = strategyFilter(intent, config);
|
|
57
|
+
if (!sf.passed)
|
|
58
|
+
continue;
|
|
59
|
+
const pf = portfolioFilter(intent, config);
|
|
60
|
+
if (!pf.passed)
|
|
61
|
+
continue;
|
|
62
|
+
const result = simulateFill(intent, snapshot);
|
|
63
|
+
if (result.success) {
|
|
64
|
+
openPosition(intent, result);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Track drawdown
|
|
68
|
+
if (equity > peakEquity)
|
|
69
|
+
peakEquity = equity;
|
|
70
|
+
const dd = (peakEquity - equity) / peakEquity;
|
|
71
|
+
if (dd > maxDrawdown)
|
|
72
|
+
maxDrawdown = dd;
|
|
73
|
+
}
|
|
74
|
+
// Close remaining positions at last price
|
|
75
|
+
const lastSnapshot = JSON.parse(rows[rows.length - 1].data_json);
|
|
76
|
+
const remaining = getPositions();
|
|
77
|
+
for (const pos of remaining) {
|
|
78
|
+
const pnl = closePosition(pos.id, lastSnapshot.ticker.lastPrice, '回测结束');
|
|
79
|
+
trades.push({
|
|
80
|
+
timestamp: lastSnapshot.timestamp,
|
|
81
|
+
strategy: pos.strategy,
|
|
82
|
+
direction: pos.direction,
|
|
83
|
+
entryPrice: pos.entryPrice,
|
|
84
|
+
exitPrice: lastSnapshot.ticker.lastPrice,
|
|
85
|
+
pnl,
|
|
86
|
+
holdingMs: lastSnapshot.timestamp - pos.openedAt,
|
|
87
|
+
reason: '回测结束平仓',
|
|
88
|
+
});
|
|
89
|
+
equity += pnl;
|
|
90
|
+
returns.push(pnl / equity);
|
|
91
|
+
}
|
|
92
|
+
const wins = trades.filter(t => t.pnl > 0).length;
|
|
93
|
+
const totalPnl = trades.reduce((s, t) => s + t.pnl, 0);
|
|
94
|
+
const avgReturn = returns.length > 0 ? returns.reduce((a, b) => a + b, 0) / returns.length : 0;
|
|
95
|
+
const stdReturn = returns.length > 1
|
|
96
|
+
? Math.sqrt(returns.reduce((s, r) => s + (r - avgReturn) ** 2, 0) / (returns.length - 1))
|
|
97
|
+
: 0;
|
|
98
|
+
const sharpe = stdReturn > 0 ? (avgReturn / stdReturn) * Math.sqrt(252) : 0;
|
|
99
|
+
return {
|
|
100
|
+
strategy: strategyFilter_ || 'all',
|
|
101
|
+
period: {
|
|
102
|
+
start: rows[0].timestamp,
|
|
103
|
+
end: rows[rows.length - 1].timestamp,
|
|
104
|
+
days,
|
|
105
|
+
},
|
|
106
|
+
snapshotsUsed: rows.length,
|
|
107
|
+
trades,
|
|
108
|
+
summary: {
|
|
109
|
+
totalTrades: trades.length,
|
|
110
|
+
wins,
|
|
111
|
+
losses: trades.length - wins,
|
|
112
|
+
winRate: trades.length > 0 ? wins / trades.length : 0,
|
|
113
|
+
totalPnl,
|
|
114
|
+
avgPnl: trades.length > 0 ? totalPnl / trades.length : 0,
|
|
115
|
+
maxDrawdown,
|
|
116
|
+
sharpeRatio: sharpe,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function emptyResult(strategy, days) {
|
|
121
|
+
return {
|
|
122
|
+
strategy,
|
|
123
|
+
period: { start: 0, end: 0, days },
|
|
124
|
+
snapshotsUsed: 0,
|
|
125
|
+
trades: [],
|
|
126
|
+
summary: {
|
|
127
|
+
totalTrades: 0, wins: 0, losses: 0, winRate: 0,
|
|
128
|
+
totalPnl: 0, avgPnl: 0, maxDrawdown: 0, sharpeRatio: 0,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/backtest/runner.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAKzI,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;AA8B7E,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAmB,EACnB,eAAmC,EACnC,IAAY;IAEZ,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,SAAS,CAAA;IAC5C,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;GAGvB,CAAC,CAAC,GAAG,CAAC,MAAM,CAAqE,CAAA;IAElF,EAAE,CAAC,KAAK,EAAE,CAAA;IAEV,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,WAAW,CAAC,eAAe,IAAI,KAAK,EAAE,IAAI,CAAC,CAAA;IACpD,CAAC;IAED,MAAM,MAAM,GAAoB,EAAE,CAAA;IAClC,IAAI,MAAM,GAAG,IAAI,CAAA;IACjB,IAAI,UAAU,GAAG,MAAM,CAAA;IACvB,IAAI,WAAW,GAAG,CAAC,CAAA;IACnB,MAAM,OAAO,GAAa,EAAE,CAAA;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAmB,CAAA;QAChE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAA;QAEvC,mBAAmB;QACnB,oBAAoB,CAAC,KAAK,CAAC,CAAA;QAE3B,gCAAgC;QAChC,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAA;QAChD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,IAAI,CAAC;gBACV,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,SAAS;gBACpC,SAAS,EAAE,GAAG,EAAE,SAAS,IAAI,MAAM;gBACnC,UAAU,EAAE,GAAG,EAAE,UAAU,IAAI,CAAC;gBAChC,SAAS,EAAE,KAAK;gBAChB,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACtD,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAA;YACF,MAAM,IAAI,CAAC,CAAC,GAAG,CAAA;YACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC,CAAA;QAC9B,CAAC;QAED,2CAA2C;QAC3C,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAA;QAC5C,IAAI,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;QAE9D,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,eAAe,CAAC,CAAA;QAC/D,CAAC;QAED,wBAAwB;QACxB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YACzC,IAAI,CAAC,EAAE,CAAC,MAAM;gBAAE,SAAQ;YACxB,MAAM,EAAE,GAAG,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAC1C,IAAI,CAAC,EAAE,CAAC,MAAM;gBAAE,SAAQ;YAExB,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;YAC7C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,IAAI,MAAM,GAAG,UAAU;YAAE,UAAU,GAAG,MAAM,CAAA;QAC5C,MAAM,EAAE,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,UAAU,CAAA;QAC7C,IAAI,EAAE,GAAG,WAAW;YAAE,WAAW,GAAG,EAAE,CAAA;IACxC,CAAC;IAED,0CAA0C;IAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,CAAmB,CAAA;IAClF,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QACxE,MAAM,CAAC,IAAI,CAAC;YACV,SAAS,EAAE,YAAY,CAAC,SAAS;YACjC,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,SAAS;YACxC,GAAG;YACH,SAAS,EAAE,YAAY,CAAC,SAAS,GAAG,GAAG,CAAC,QAAQ;YAChD,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,CAAA;QACb,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,CAAA;IAC5B,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAA;IACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACtD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9F,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC;QAClC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC,CAAA;IACL,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAE3E,OAAO;QACL,QAAQ,EAAE,eAAe,IAAI,KAAK;QAClC,MAAM,EAAE;YACN,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;YACxB,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS;YACpC,IAAI;SACL;QACD,aAAa,EAAE,IAAI,CAAC,MAAM;QAC1B,MAAM;QACN,OAAO,EAAE;YACP,WAAW,EAAE,MAAM,CAAC,MAAM;YAC1B,IAAI;YACJ,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI;YAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACrD,QAAQ;YACR,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACxD,WAAW;YACX,WAAW,EAAE,MAAM;SACpB;KACF,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB,EAAE,IAAY;IACjD,OAAO;QACL,QAAQ;QACR,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE;QAClC,aAAa,EAAE,CAAC;QAChB,MAAM,EAAE,EAAE;QACV,OAAO,EAAE;YACP,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;YAC9C,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;SACvD;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface BasisSnapshot {
|
|
2
|
+
timestamp: number;
|
|
3
|
+
bfxPrice: number;
|
|
4
|
+
binancePrice: number | null;
|
|
5
|
+
bfxVsBinance: number | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function fetchBinancePrice(): Promise<number | null>;
|
|
8
|
+
export declare function calculateBasis(bfxPrice: number): Promise<BasisSnapshot>;
|
|
9
|
+
//# sourceMappingURL=basis-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-monitor.d.ts","sourceRoot":"","sources":["../../../src/collector/basis-monitor.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAsBD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOhE;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiB7E"}
|