@timmeck/trading-brain 2.31.61 → 2.31.63

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.
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function backtestCommand(): Command;
@@ -0,0 +1,42 @@
1
+ import { Command } from 'commander';
2
+ import { withIpc } from '../ipc-helper.js';
3
+ import { c, icons, header, keyValue } from '../colors.js';
4
+ export function backtestCommand() {
5
+ const cmd = new Command('backtest')
6
+ .description('Run backtests on historical data');
7
+ cmd
8
+ .command('strategy <id>')
9
+ .description('Backtest a StrategyForge strategy on historical OHLCV data')
10
+ .option('-p, --pair <pair>', 'Trading pair', 'BTC/USDT')
11
+ .option('-d, --days <n>', 'Days of history', '30')
12
+ .action(async (id, opts) => {
13
+ await withIpc(async (client) => {
14
+ console.log(header('Strategy Backtest', icons.chart));
15
+ console.log(c.dim(` Testing strategy #${id} on ${opts.pair} (${opts.days}d)...\n`));
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ const result = await client.request('backtest.strategy', {
18
+ strategyId: parseInt(id, 10),
19
+ pair: opts.pair,
20
+ days: parseInt(opts.days, 10),
21
+ });
22
+ if (result.totalTrades === 0) {
23
+ console.log(c.orange(` ${icons.warn} No trades generated. Strategy rules may not match the data.`));
24
+ return;
25
+ }
26
+ const winColor = result.winRate >= 0.5 ? c.green : c.red;
27
+ const returnColor = result.totalReturnPct >= 0 ? c.green : c.red;
28
+ console.log(keyValue('Strategy', result.strategyName));
29
+ console.log(keyValue('Pair', result.pair));
30
+ console.log(keyValue('Period', `${result.days} days`));
31
+ console.log(keyValue('Total Trades', String(result.totalTrades)));
32
+ console.log(keyValue('Win Rate', winColor(`${(result.winRate * 100).toFixed(1)}% (${result.wins}W / ${result.losses}L)`)));
33
+ console.log(keyValue('Total Return', returnColor(`${result.totalReturnPct >= 0 ? '+' : ''}${result.totalReturnPct.toFixed(2)}%`)));
34
+ console.log(keyValue('Avg Return', `${result.avgReturnPct.toFixed(2)}%`));
35
+ console.log(keyValue('Max Drawdown', c.red(`${result.maxDrawdownPct.toFixed(2)}%`)));
36
+ console.log(keyValue('Profit Factor', result.profitFactor === Infinity ? '∞' : result.profitFactor.toFixed(2)));
37
+ console.log(keyValue('Sharpe Ratio', result.sharpeRatio.toFixed(2)));
38
+ });
39
+ });
40
+ return cmd;
41
+ }
42
+ //# sourceMappingURL=backtest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backtest.js","sourceRoot":"","sources":["../../../src/cli/commands/backtest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function strategyCommand(): Command;
@@ -0,0 +1,52 @@
1
+ import { Command } from 'commander';
2
+ import fs from 'node:fs';
3
+ import { withIpc } from '../ipc-helper.js';
4
+ import { c, icons, header } from '../colors.js';
5
+ export function strategyCommand() {
6
+ const cmd = new Command('strategy')
7
+ .description('Strategy management (export/import)');
8
+ cmd
9
+ .command('export <id>')
10
+ .description('Export a strategy as JSON')
11
+ .option('-f, --file <path>', 'Output file path')
12
+ .action(async (id, opts) => {
13
+ await withIpc(async (client) => {
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ const result = await client.request('strategy.export', { id: parseInt(id, 10) });
16
+ const json = JSON.stringify(result, null, 2);
17
+ if (opts.file) {
18
+ fs.writeFileSync(opts.file, json);
19
+ console.log(`${icons.ok} ${c.green(`Strategy exported to ${opts.file}`)}`);
20
+ }
21
+ else {
22
+ console.log(json);
23
+ }
24
+ });
25
+ });
26
+ cmd
27
+ .command('import <file>')
28
+ .description('Import a strategy from JSON file')
29
+ .action(async (file) => {
30
+ await withIpc(async (client) => {
31
+ if (!fs.existsSync(file)) {
32
+ console.error(`${icons.error} File not found: ${file}`);
33
+ process.exit(1);
34
+ }
35
+ const json = fs.readFileSync(file, 'utf-8');
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ const result = await client.request('strategy.import', { json });
38
+ if (!result.success) {
39
+ console.error(`${icons.error} Import failed: ${result.error}`);
40
+ process.exit(1);
41
+ }
42
+ console.log(header('Strategy Imported', icons.ok));
43
+ console.log(` Name: ${c.green(result.strategyName)}`);
44
+ console.log(` ID: ${c.cyan(String(result.strategyId))}`);
45
+ console.log(` Status: ${c.dim('draft')}`);
46
+ console.log();
47
+ console.log(c.dim(` Tip: Run 'trading backtest strategy ${result.strategyId}' to validate`));
48
+ });
49
+ });
50
+ return cmd;
51
+ }
52
+ //# sourceMappingURL=strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../../src/cli/commands/strategy.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -33,6 +33,8 @@ import { dashboardCommand } from './cli/commands/dashboard.js';
33
33
  import { peersCommand } from './cli/commands/peers.js';
34
34
  import { setupCommand } from './cli/commands/setup.js';
35
35
  import { paperCommand } from './cli/commands/paper.js';
36
+ import { backtestCommand } from './cli/commands/backtest.js';
37
+ import { strategyCommand } from './cli/commands/strategy.js';
36
38
  import { checkForUpdate, getCurrentVersion } from './cli/update-check.js';
37
39
  const program = new Command();
38
40
  program
@@ -54,6 +56,8 @@ program.addCommand(dashboardCommand());
54
56
  program.addCommand(peersCommand());
55
57
  program.addCommand(setupCommand());
56
58
  program.addCommand(paperCommand());
59
+ program.addCommand(backtestCommand());
60
+ program.addCommand(strategyCommand());
57
61
  // Hidden command: run MCP server (called by Claude Code)
58
62
  program
59
63
  .command('mcp-server')
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { getLogger } from '../utils/logger.js';
2
2
  import { getCurrentVersion } from '../cli/update-check.js';
3
+ import { StrategyExporter, StrategyImporter } from '@timmeck/brain-core';
3
4
  const logger = getLogger();
4
5
  export class IpcRouter {
5
6
  services;
@@ -146,6 +147,23 @@ export class IpcRouter {
146
147
  }],
147
148
  ['backtest.compare', (params) => s.backtest.compareSignals(p(params).fingerprint1, p(params).fingerprint2)],
148
149
  ['backtest.bestSignals', (params) => s.backtest.findBestSignals(p(params))],
150
+ ['backtest.strategy', async (params) => {
151
+ if (!s.strategyForge)
152
+ throw new Error('StrategyForge not available');
153
+ const { strategyId, pair, days } = p(params);
154
+ const strategy = s.strategyForge.getStrategy(strategyId);
155
+ if (!strategy)
156
+ throw new Error(`Strategy #${strategyId} not found`);
157
+ let candles = [];
158
+ if (s.marketData) {
159
+ try {
160
+ candles = await s.marketData.fetchOHLCV(pair ?? 'bitcoin', '1h', Math.min((days ?? 30) * 24, 720));
161
+ }
162
+ catch { /* use empty candles → 0 trades */ }
163
+ }
164
+ const result = s.backtest.runStrategyBacktest(strategy, candles, { pair });
165
+ return result;
166
+ }],
149
167
  // ─── Risk ─────────────────────────────────────────
150
168
  ['risk.kelly', (params) => s.risk.getKellyFraction(p(params).pair, p(params).regime)],
151
169
  ['risk.positionSize', (params) => s.risk.getPositionSize(p(params).capitalPct, p(params).signals, p(params).regime)],
@@ -953,6 +971,18 @@ export class IpcRouter {
953
971
  throw new Error('StrategyForge not available'); return s.strategyForge.retire(p(params).id, p(params).reason); }],
954
972
  ['strategy.status', () => { if (!s.strategyForge)
955
973
  throw new Error('StrategyForge not available'); return s.strategyForge.getStatus(); }],
974
+ ['strategy.export', (params) => {
975
+ if (!s.strategyForge)
976
+ throw new Error('StrategyForge not available');
977
+ const exporter = new StrategyExporter(s.strategyForge);
978
+ return exporter.exportObject(p(params).id);
979
+ }],
980
+ ['strategy.import', (params) => {
981
+ if (!s.strategyForge)
982
+ throw new Error('StrategyForge not available');
983
+ const importer = new StrategyImporter(s.strategyForge);
984
+ return importer.import(typeof p(params).json === 'string' ? p(params).json : JSON.stringify(p(params).json));
985
+ }],
956
986
  ['strategy.bridge.status', () => {
957
987
  if (!s.strategyForge || !s.actionBridge)
958
988
  throw new Error('StrategyForge or ActionBridge not available');