LogoMalgotDocsPricing
Sign In

2 · Developing

Stable
Express your hypothesis as a Python strategy, with indicators and observers, inside Malgot's engine.

In Malgot you write strategies in Python, and they run inside a Rust engine. You get Python's expressiveness for the decision logic and Rust's speed and determinism for the simulation loop. A trading system is assembled from a few small, composable objects.

The building blocks

| Object | Role | Language | |---|---|---| | Strategy | Decides what to trade — emits signals each bar | Python | | Indicator | A reusable computed series (SMA, RSI, Z-Score…) | Python | | Observer | Records a value each bar for charting (equity, exposure…) | Python | | Metric | A single end-of-run number (CAGR, Sharpe…) | Python | | Signal Allocator | Turns raw signals into sized orders | configured | | Broker | Fees, slippage, margin, borrow — the cost model | configured |

You develop these in the Object Explorer (/framework), each with an in-browser Monaco editor.

Anatomy of a strategy

A strategy subclasses Malgot.Strategy and implements evaluate(), returning a list of Malgot.Signal. Indicators are linked to the strategy and read back by name:

python
import Malgot
import numpy as np

class MyMeanReversion(Malgot.Strategy):
    def __init__(self):
        super().__init__()
        self.name = "My Mean Reversion"
        # Defaults — overridden by DB-linked strategy parameters.
        self.entry_z = 1.25
        self.exit_z = 0.5

    def evaluate(self):
        signals = []
        symbols = self.data.get_symbols()

        # Linked indicator, aligned column-for-column with `symbols`.
        z = self.state.get_indicator_values("Z-Score", symbols)
        held = dict(self.state.get_all_positions())   # {symbol: qty}

        for i, symbol in enumerate(symbols):
            zi = float(z[i])
            price = self.data.get_current_price(symbol)
            if np.isnan(zi) or price <= 0:
                continue

            if symbol in held:
                # Exit when the deviation has reverted.
                if zi >= -self.exit_z:
                    signals.append(Malgot.Signal(symbol, "SELL", held[symbol]))
            elif zi <= -self.entry_z:
                # Enter on a statistically extreme dip.
                size = (0.01 * self.state.total_value) / price
                signals.append(Malgot.Signal(symbol, "BUY", size))

        return signals
Parameters belong in the database, not hard-coded

Give every knob a strategy parameter (with min/max/default). __init__ holds only fallbacks. This is what makes the same strategy tunable from the UI and, later, optimizable without touching code.

Signals carry intent, not just direction

A Signal can specify order type and risk legs, which the engine's broker turns into real orders:

python
Malgot.Signal(
    symbol, "BUY", size,
    order_type="LIMIT", limit_price=99.5,
    stop_loss=95.0, take_profit=110.0,
    time_in_force="GTC",
)

Market, limit, stop, stop-limit, trailing, and on-open/close orders are supported, plus bracket exits (OCO). Keep the strategy about when to trade; let the broker and signal allocator own sizing and execution mechanics.

Make it observable

You can only debug — and later trust — what you can see. Add observers for the quantities that explain the equity curve: net exposure, number of open positions, cash ratio, per-sleeve position value. When a backtest surprises you, observers are where you look first.

Separate concerns

Don't bake costs or sizing into the strategy

Commission, slippage, borrow fees and position sizing live in the broker and allocator — not in evaluate(). This keeps the strategy portable across cost models and lets you stress-test costs later without editing logic.

In Malgot today

Stable
Fully supported. Author strategies, indicators, observers and metrics in the Object Explorer; link indicators to strategies; expose parameters; configure a broker and signal allocator. Everything you write here runs unchanged in Backtesting and, eventually, live.


Previous

1 · Trading idea & research

Next

3 · Backtesting