package backtest import ( "context" "fmt" "git.toki-labs.com/toki/alt/packages/domain/backtest" "git.toki-labs.com/toki/alt/packages/domain/market" ) // BuiltInStrategyID is the identifier of the worker's default bundled strategy. // Command workflows and YAML scenarios reference it so a backtest can run // end-to-end on imported bars without an operator authoring a custom strategy. const BuiltInStrategyID backtest.StrategyID = "strategy-v1" // BuiltInStrategyPort resolves the worker's bundled strategies. It is the // production StrategyPort wired in cmd/alt-worker. Unknown ids return an error // so a misconfigured run fails fast instead of silently producing an empty // result. type BuiltInStrategyPort struct{} func NewBuiltInStrategyPort() *BuiltInStrategyPort { return &BuiltInStrategyPort{} } func (p *BuiltInStrategyPort) GetStrategy(ctx context.Context, id backtest.StrategyID) (backtest.Strategy, error) { switch id { case BuiltInStrategyID: return buyAndHoldStrategy{id: id}, nil default: return nil, fmt.Errorf("unknown strategy %q", id) } } // buyAndHoldStrategy buys a single unit of each instrument the first time it is // seen and then holds. It is intentionally minimal and deterministic so command // validation can assert a stable terminal result from imported daily bars. type buyAndHoldStrategy struct { id backtest.StrategyID } func (s buyAndHoldStrategy) ID() backtest.StrategyID { return s.id } func (s buyAndHoldStrategy) Decide(input backtest.StrategyInput) ([]backtest.OrderIntent, error) { // Hold once a position exists. The engine passes the pre-trade portfolio for // the current bar, so an existing position means this instrument was already // bought on an earlier bar. if _, held := input.Portfolio.Position(input.Bar.InstrumentID); held { return nil, nil } return []backtest.OrderIntent{ { InstrumentID: input.Bar.InstrumentID, Side: backtest.OrderSideBuy, Quantity: market.Quantity{Amount: market.Decimal{Value: "1"}}, }, }, nil }