Spaces:
Sleeping
Sleeping
| """ | |
| 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 | |