Strategy authoring

A strategy is just two functions — init, run once before the backtest loop, and next, run once per bar — wired to a concrete struct via @generate_strategy; see the Tutorial for a worked example.

Orcus.initFunction
init(s::Strategy)

Called once before the backtest loop starts; typically attaches indicators. Errors unless wired via @generate_strategy/@strategy_methods.

struct Dummy <: Strategy end
try
    init(Dummy())
catch e
    println(sprint(showerror, e))
end
# output

No init method defined for Strategy "Dummy"
source
Orcus.nextFunction
next(s::Strategy)

Called once per bar; the strategy's per-bar logic. Errors unless wired via @generate_strategy/@strategy_methods.

struct Dummy <: Strategy end
try
    next(Dummy())
catch e
    println(sprint(showerror, e))
end
# output

No next method defined for Strategy "Dummy"
source
Orcus.@generate_strategyMacro
@generate_strategy StrategyName next_fn init_fn field...

Generate a Strategy subtype named StrategyName, wired to call next_fn/init_fn for its next/init methods. Each trailing field is name, name::Type, name = default, or name::Type = default — swept parameters for batch_backtest should be typed. Like @strategy_methods, must be invoked where next_fn/init_fn resolve in Main — a top-level script or REPL session, not from inside a package, module, or test.

tmp_next(s) = nothing;
tmp_init(s) = nothing;
@generate_strategy TestStrategy tmp_next tmp_init;
s = TestStrategy(Broker(Market(),1000));
s isa Strategy
# output

true
source
Orcus.@strategy_methodsMacro
@strategy_methods StrategyName next_fn init_fn

Wire next/init dispatch for a manually-defined Strategy subtype (one with custom fields beyond broker/market), calling next_fn/init_fn. Use @generate_strategy instead when a generated struct is enough. Like @generate_strategy, must be invoked where StrategyName resolves in Main — a top-level script or REPL session, not from inside a package, module, or test.

mutable struct MyStrat <: Strategy
    broker::Broker
    market::Market
    MyStrat(b::Broker) = new(b, b.market)
end
my_next(s) = nothing
my_init(s) = nothing
@strategy_methods MyStrat my_next my_init
s = MyStrat(Broker(Market(), 1000))

Not a jldoctest: @strategy_methods resolves StrategyName in Main, which Documenter's sandboxed doctest module can't satisfy — run this in a real top-level script or REPL session instead.

source