Skip to content

Strategy Classes (Python & Codon)

Flox provides event-driven Strategy base classes for both Python and Codon that mirror the C++ Strategy class. This enables writing trading strategies in a familiar Python-like syntax while leveraging the C++ execution engine.

Architecture

C++ Strategy (fastest)
      |
  C API Layer (libflox_capi.so)
      |                |
Python Strategy    Codon Strategy
(pybind11)         (C FFI, compiled)

Python Strategy

import flox_py as flox

class SmaCrossover(flox.Strategy):
    def __init__(self, symbols, fast=10, slow=30):
        super().__init__(symbols)
        self.prices = []
        self.fast = fast
        self.slow = slow

    def on_trade(self, ctx, trade):
        self.prices.append(trade.price)
        if len(self.prices) < self.slow:
            return

        fast_sma = sum(self.prices[-self.fast:]) / self.fast
        slow_sma = sum(self.prices[-self.slow:]) / self.slow

        if fast_sma > slow_sma and ctx.is_flat():
            self.emit_market_buy(ctx.symbol_id, 1.0)
        elif fast_sma < slow_sma and ctx.is_long():
            self.emit_close_position(ctx.symbol_id)

Codon Strategy

from flox.strategy import Strategy
from flox.context import SymbolContext
from flox.types import TradeData
from flox.indicators import StreamingSMA

class SmaCrossover(Strategy):
    fast_sma: StreamingSMA
    slow_sma: StreamingSMA

    def __init__(self, symbols: List[int], fast: int = 10, slow: int = 30):
        super().__init__(symbols)
        self.fast_sma = StreamingSMA(fast)
        self.slow_sma = StreamingSMA(slow)

    def on_trade(self, ctx: SymbolContext, trade: TradeData):
        price = trade.price.to_double()
        fast = self.fast_sma.update(price)
        slow = self.slow_sma.update(price)
        if not self.slow_sma.ready:
            return

        sym = self._symbols[0]
        if fast > slow and ctx.is_flat():
            self.emit_market_buy(sym, 1.0)
        elif fast < slow and ctx.is_long():
            self.emit_close_position(sym)

API Reference

Overridable Callbacks

Method Description
on_trade(ctx, trade) Called on each trade event
on_book_update(ctx) Called on each book update
on_start() Called when strategy starts
on_stop() Called when strategy stops

Signal Emission

Method Description
emit_market_buy(symbol, qty) Submit market buy order
emit_market_sell(symbol, qty) Submit market sell order
emit_limit_buy(symbol, price, qty) Submit limit buy order
emit_limit_sell(symbol, price, qty) Submit limit sell order
emit_cancel(order_id) Cancel an order
emit_cancel_all(symbol) Cancel all orders for symbol
emit_modify(order_id, price, qty) Modify existing order
emit_stop_market(symbol, side, trigger, qty) Stop market order
emit_stop_limit(symbol, side, trigger, limit, qty) Stop limit order
emit_take_profit_market(symbol, side, trigger, qty) Take profit market
emit_take_profit_limit(symbol, side, trigger, limit, qty) Take profit limit
emit_trailing_stop(symbol, side, offset, qty) Trailing stop
emit_trailing_stop_percent(symbol, side, bps, qty) Trailing stop (%)
emit_close_position(symbol) Close entire position

Context Queries

Method Description
position(symbol) Current position as float
ctx(symbol) Get SymbolContext for a symbol
get_order_status(order_id) Order status (-1 if not found)

SymbolContext Properties

Property Description
symbol_id Symbol identifier
position Current position quantity
last_trade_price Last trade price
best_bid Best bid price
best_ask Best ask price
mid_price Mid price
book_spread() Bid-ask spread
is_long() / is_short() / is_flat() Position state

TradeData Properties

Property Description
symbol Symbol ID
price Trade price (float)
quantity Trade quantity (float)
is_buy Whether trade was a buy
timestamp_ns Exchange timestamp in nanoseconds

C++ Equivalent

The Strategy classes mirror the C++ flox::Strategy:

Python/Codon C++
on_trade(ctx, trade) onSymbolTrade(SymbolContext&, TradeEvent&)
on_book_update(ctx) onSymbolBook(SymbolContext&, BookUpdateEvent&)
on_start() / on_stop() start() / stop()
emit_market_buy(sym, qty) emitMarketBuy(sym, qty)
emit_market_sell(sym, qty) emitMarketSell(sym, qty)
emit_limit_buy(sym, price, qty) emitLimitBuy(sym, price, qty)
emit_limit_sell(sym, price, qty) emitLimitSell(sym, price, qty)
emit_cancel(order_id) emitCancel(orderId)
emit_cancel_all(sym) emitCancelAll(sym)
emit_modify(order_id, price, qty) emitModify(orderId, price, qty)
emit_stop_market(sym, side, trigger, qty) emitStopMarket(sym, side, trigger, qty)
emit_stop_limit(sym, side, trigger, limit, qty) emitStopLimit(sym, side, trigger, limit, qty)
emit_take_profit_market(sym, side, trigger, qty) emitTakeProfitMarket(sym, side, trigger, qty)
emit_take_profit_limit(sym, side, trigger, limit, qty) emitTakeProfitLimit(sym, side, trigger, limit, qty)
emit_trailing_stop(sym, side, offset, qty) emitTrailingStop(sym, side, offset, qty)
emit_trailing_stop_percent(sym, side, bps, qty) emitTrailingStopPercent(sym, side, bps, qty)
emit_close_position(sym) emitClosePosition(sym)
position(sym) position(sym)
ctx(sym) ctx(sym)
get_order_status(order_id) getOrderStatus(orderId)