quant-knowledge-extractor / src /QuantEngine.jl
cyberkyne's picture
Upload 22 files
1a56c89 verified
"""
QuantEngine.jl β€” Top-level module. Only file that uses include().
Wires all submodules together by injecting dependencies explicitly.
Python imports this via juliacall.
"""
module QuantEngine
using Statistics, Random
# ── Include all submodules (ONLY here) ───────────────
include("Indicators.jl")
include("BacktestEngine.jl")
include("Optimizer.jl")
include("SignalCompiler.jl")
using .Indicators
using .BacktestEngine
using .Optimizer
using .SignalCompiler
export
# Indicators
sma, ema, wma, tema, dema,
rsi, macd, stoch, cci, williams_r,
atr, bbands, keltner, donchian, adx,
vwap, obv, cmf, zscore, std_dev,
momentum, roc, highest, lowest,
crossover, crossunder,
# Engine
BacktestConfig, run_backtest,
# High-level
full_backtest_pipeline
"""
full_backtest_pipeline(...) -> Dict{String,Any}
End-to-end: compile Julia strategy code β†’ walk-forward optimize
β†’ return plain Dict that crosses to Python cleanly.
"""
function full_backtest_pipeline(
strategy_code::String, strategy_name::String,
open_p::Vector{Float64}, high::Vector{Float64},
low::Vector{Float64}, close::Vector{Float64},
volume::Vector{Float64}, timeframe::String, symbol::String;
n_windows::Int=5, is_ratio::Float64=0.70,
min_trades::Int=30, min_sharpe::Float64=0.5,
max_combos::Int=300,
initial_equity::Float64=10_000.0,
commission_pct::Float64=0.0002,
risk_per_trade::Float64=0.01,
)::Dict{String,Any}
# 1. Compile strategy β€” pass Indicators module explicitly
compiled = SignalCompiler.compile_strategy(strategy_name, strategy_code, Indicators)
if !compiled.is_valid
return Dict{String,Any}("is_valid"=>false,"error"=>compiled.error,
"strategy"=>strategy_name,"symbol"=>symbol,"timeframe"=>timeframe)
end
# 2. Walk-forward optimize β€” inject BacktestEngine functions to avoid circular deps
cfg_fn = () -> BacktestConfig(
initial_equity=initial_equity,
commission_pct=commission_pct,
risk_per_trade=risk_per_trade,
)
# Wrap run_backtest to inject atr function from Indicators
run_bt_fn = (o,h,l,c,v,sigs,tf,cfg) ->
BacktestEngine.run_backtest(o,h,l,c,v,sigs,tf,cfg, Indicators.atr)
opt = Optimizer.walk_forward_optimize(
compiled.generate_fn,
compiled.param_grid_fn(),
open_p, high, low, close, volume,
timeframe, strategy_name, symbol;
run_bt_fn=run_bt_fn,
bt_cfg_fn=cfg_fn,
n_windows=n_windows, is_ratio=is_ratio,
min_trades=min_trades, min_sharpe=min_sharpe,
max_combos=max_combos,
)
return Dict{String,Any}(
"is_valid" => true,
"strategy" => opt.strategy_name,
"symbol" => opt.symbol,
"timeframe" => opt.timeframe,
"optimal_params" => opt.optimal_params,
"oos_sharpe_mean" => opt.oos_sharpe_mean,
"oos_sharpe_std" => opt.oos_sharpe_std,
"oos_win_rate" => opt.oos_win_rate,
"oos_max_dd" => opt.oos_max_dd,
"oos_pf_mean" => opt.oos_pf_mean,
"oos_trades" => opt.oos_trades,
"wf_efficiency" => opt.wf_efficiency,
"robustness" => opt.robustness,
"is_viable" => opt.is_viable,
"reasons" => opt.reasons,
"oos_sharpes" => opt.oos_sharpes,
)
end
end # module QuantEngine