moving engine to rust

This commit is contained in:
Boki 2025-07-03 20:10:33 -04:00
parent d14380d740
commit 16ac28a565
16 changed files with 1598 additions and 3 deletions

View file

@ -0,0 +1,139 @@
import { BacktestEngine } from '@stock-bot/core';
import { MarketData } from '../types';
export interface Signal {
symbol: string;
signal_type: 'Buy' | 'Sell' | 'Close';
strength: number; // -1.0 to 1.0
quantity?: number;
reason?: string;
metadata?: any;
}
export interface StrategyCall {
method: string;
data: any;
}
export interface StrategyResponse {
signals: Signal[];
}
/**
* Base class for TypeScript strategies that run in the Rust backtest engine
*/
export abstract class RustStrategy {
protected name: string;
protected id: string;
protected parameters: Record<string, any>;
protected positions: Map<string, number> = new Map();
constructor(name: string, id: string, parameters: Record<string, any> = {}) {
this.name = name;
this.id = id;
this.parameters = parameters;
}
/**
* Main callback that Rust will call
*/
public handleCall(call: StrategyCall): StrategyResponse {
switch (call.method) {
case 'on_market_data':
const signals = this.onMarketData(call.data);
return { signals };
case 'on_fill':
this.onFill(
call.data.symbol,
call.data.quantity,
call.data.price,
call.data.side
);
return { signals: [] };
default:
return { signals: [] };
}
}
/**
* Called when new market data is received
*/
protected abstract onMarketData(data: MarketData): Signal[];
/**
* Called when an order is filled
*/
protected onFill(symbol: string, quantity: number, price: number, side: string): void {
const currentPosition = this.positions.get(symbol) || 0;
const newPosition = side === 'buy' ?
currentPosition + quantity :
currentPosition - quantity;
if (Math.abs(newPosition) < 0.0001) {
this.positions.delete(symbol);
} else {
this.positions.set(symbol, newPosition);
}
}
/**
* Helper to create a buy signal
*/
protected buySignal(symbol: string, strength: number = 1.0, reason?: string): Signal {
return {
symbol,
signal_type: 'Buy',
strength,
reason,
};
}
/**
* Helper to create a sell signal
*/
protected sellSignal(symbol: string, strength: number = 1.0, reason?: string): Signal {
return {
symbol,
signal_type: 'Sell',
strength,
reason,
};
}
/**
* Helper to create a close position signal
*/
protected closeSignal(symbol: string, reason?: string): Signal {
return {
symbol,
signal_type: 'Close',
strength: 1.0,
reason,
};
}
/**
* Register this strategy with a backtest engine
*/
public register(engine: BacktestEngine): void {
console.log(`Registering strategy ${this.name} with id ${this.id}`);
// Convert the handleCall method to what Rust expects
const callback = (callJson: string) => {
console.log('Strategy callback called with:', callJson);
const call: StrategyCall = JSON.parse(callJson);
const response = this.handleCall(call);
console.log('Strategy response:', response);
return JSON.stringify(response);
};
engine.addTypescriptStrategy(
this.name,
this.id,
this.parameters,
callback as any
);
}
}