Quantstrat Strategy Builder

1. Initialize

to

            

1b. Example Strategies

Each button below builds a complete, real strategy -- indicators, signals, and rules -- using the same recipe engine that pre-fills the manual pickers on the next pages (R/strategy_recipes.R), via real add.indicator()/add.signal()/add.rule() calls. Fully editable/removable afterward on Steps 2-4, same as anything added by hand. Replaces whatever strategy content already exists. More will be added here over time.


            

1c. Strategy Management

Save/load operate on just the strategy DEFINITION (indicators, signals, rules) via quantstrat's own save.strategy()/load.strategy() -- confirmed in their installed source: they read/write only the strategy object itself, independent of portfolio/account/market data. Loading a strategy still requires '1. Initialize' to have already set up symbols/dates/portfolio first. Remove clears all live state for this name (order book, portfolio, account, AND the strategy object -- quantstrat's own rm.strat(), confirmed in its source) and returns this app to "not initialized".


            

2. Add Indicators


                  
Indicators added so far

2b. Add Signals


                  
Signals added so far
applySignals() status

            

2c. Add Rules


                  
Rules added so far
Enable / disable a rule (quantstrat::enable.rule())
Preview: applyRules() -- real orders generated

Resets the order book for the first symbol, then runs the real quantstrat::applyRules() across the full signal-augmented history -- the exact same call applyStrategy() makes internally per documentation/github_repos/quantstrat's own source. Shows the real orders your rules generated via getOrderBook() -- no position/P&L tracking here; see 2d below for the full backtest.


              

2d. Position Limits (quantstrat::addPosLimit())

Optional -- only needed if a rule's osFUN is set to osMaxPos (see 2c above), which real-errors at apply time without a limit set first (confirmed live). Sets the maximum position size osMaxPos will size orders up to.


        

2e. Run Backtest

Runs the real quantstrat::applyStrategy() -- the same applyIndicators() -> applySignals() -> applyRules() chain as the previews above, but looped across the full date range for every symbol, with real order fills (quantstrat's own built-in ruleOrderProc() runs automatically each bar when no explicit "order"-type rule exists, confirmed in documentation/github_repos/ quantstrat/R/rules.R) -- then blotter::updatePortf()/updateAcct()/ updateEndEq() to turn those fills into real positions, P&L, and an equity curve. Resets the portfolio/account/order book fresh each click (never the strategy itself) so repeated runs don't double-count transactions on top of a previous run.


          
Trade stats (blotter::tradeStats())
Equity curve (Account End.Eq)
Trade order stats (quantstrat::tradeOrderStats()) -- for the symbol picked in the Chart section below

2f. Order Management

getOrders() (filtered view of the real order book) and updateOrders() (bulk status transitions, e.g. canceling every still-open order) -- both real quantstrat exports, confirmed against their installed source. Acts on the order book left behind by whichever ran last: 2c's rule preview or 2e's full backtest.


          
Bulk update: transition matching orders to a new status (updateOrders())

          

3. Chart

The backtest above runs across every symbol in the portfolio -- pick which one to display below (chart, bars table, and the trade order stats table above all follow this selection).

Most recent bars


4. Multi-Symbol Signal Scan — experimental (quantstrat::applyIndicatorSignals())

Runs the real applyIndicatorSignals() across every symbol in the portfolio (all symbols entered above, not just the first one the rest of this app uses), extracting ONE chosen signal column per symbol into a single comparison table. Caveat, confirmed in unit_tests/applyIndicatorsSignals/combined/: this only works correctly for a signal built from an INDICATOR-derived column (e.g. an SMA/RSI label) -- a signal referencing a raw price column like "AAPL.Close" only exists for that one symbol. For OTHER symbols it can fail two different ways depending on the signal function: sigThreshold-style functions error outright, but sigComparison/sigCrossover instead fail SILENTLY -- no error at all, the signal just never fires for that symbol, which is easy to miss. Stick to indicator-derived columns for anything meant to run across more than one symbol.


          

5. Parameter Optimization (Paramsets)

Builds a real quantstrat paramset via add.distribution() -- vary one argument of an already-added indicator or rule across a set of candidate values -- then runs apply.paramset() (real applyStrategy(), once per parameter combination, via the foreach package) to compare how each combination performed. Uses a Windows-safe parallel PSOCK cluster (parallel::makePSOCKcluster()), the same approach already used by this app's own indicator stress-test suite.

Add a distribution (quantstrat::add.distribution())

                  
Distributions added so far
Add a constraint between two distributions (optional)

                  
Constraints added so far
Run optimization

                

6. Robustness Diagnostics

Real quantstrat overfitting/multiple-testing diagnostics, run against the trial portfolios from the paramset optimization run above (deflatedSharpe/haircutSharpe are real aliases of SharpeRatio.deflated/SharpeRatio.haircut, profitHurdle of profit.hurdle -- confirmed via identical(body(...)) against the installed quantstrat 0.25). trials= is the real per-run parameter-combination count tracked by this app itself, not quantstrat's own strategy$trials field -- that field silently accumulates across repeated apply.paramset() clicks with no reset (confirmed in its real source), so it's deliberately not relied on here.


            
degrees.of.freedom()
deflatedSharpe() / haircutSharpe() / profitHurdle()

7. Walk-Forward Analysis (quantstrat::walk.forward())

Rolls a training/testing window across the whole date range: for each training period, runs apply.paramset() to pick the parameter combination with the highest Net.Trading.PL (quantstrat's own real default objective function -- confirmed in its installed source, not overridden here), then applies exactly that combination out-of-sample on the following testing period. Requires a paramset (built in section 5 above) to already exist.


          
Parameter combo chosen per testing period
Out-of-sample trade stats (aggregated across all testing periods)

            

8. Signal Research Lab (quantstrat's post-hoc signal-analysis tools)

Real quantstrat tools for studying an already-computed signal's forward-return behavior -- not signal generators (those are in step 2b). post.signal.returns() works on any single signal column below; the multi-variant section further down needs a paramset (section 5 above) and runs the real apply.paramset.signal.analysis() orchestrator across every trial and every symbol. signal.path.plot() is not implemented here -- it needs the unmaintained, GitHub-only rCharts package, see FEATURE_PARITY.md.

Single signal: post.signal.returns()

Computed against the symbol picked in the Chart section above (currently: )


          
Forward returns by day

Multi-variant: apply.paramset.signal.analysis()

Runs post.signal.returns() + signal.generate.statistics() (obj.fun = quantstrat::signal.obj.slope -- quantstrat's own real example objective function, the only one it ships) across every trial in the chosen paramset and every symbol in the portfolio.


          
Objective value per trial per symbol (signal.obj.slope)
Forward-return distribution per trial (selected display symbol)
💬 Strategy Assistant

Ask about what an indicator/signal/rule argument does, or tell it to change something (e.g. "update the order quantity on EnterLong to 2000"). It only has tools for the part of the strategy you've reached so far.