Multi-Timeframe Strategies ========================== Most professional strategies don't operate on a single timeframe. They use a slower timeframe for portfolio decisions and a faster timeframe for daily risk management. Quantlens supports up to **four independent intervals** in one strategy. ---- .. contents:: On this page :local: :depth: 1 ---- The four intervals ------------------- The :ref:`config` block exposes four independently configurable intervals: .. list-table:: :header-rows: 1 :widths: 25 20 55 * - Interval - Default - Typical use * - **Primary** - ``2w`` - Main rebalancing logic — stock selection, ranking, entering/exiting positions. * - **Secondary** - ``1d`` - Daily risk management — stop-loss checks, limit order execution. * - **Tertiary** - ``2d`` - Mid-frequency checks — secondary condition monitoring, partial exits. * - **Quaternary** - ``2w`` - Low-frequency oversight — market regime filter re-evaluation. Each interval maps to a **On Interval** block in your workspace. Blocks nested inside a On Interval only execute when that interval fires. **Interval format:** .. code-block:: text 1d = every trading day 2d = every 2 trading days 1w = every week (Monday) 2w = every 2 weeks 1m = every calendar month ---- The classic two-timeframe setup --------------------------------- The most widely used pattern is **weekly rebalance + daily risk management**: .. code-block:: text Primary Interval: 1w (or 2w) Secondary Interval: 1d **Primary (weekly)** — stock selection: 1. Rank stocks by momentum (or RSI condition). 2. Apply market filter (Index > SMA200). 3. Enter top-ranked positions. 4. Exit positions that dropped out of the top. **Secondary (daily)** — risk management: 1. Check stop-losses on all open positions. 2. Execute any pending limit orders. **Why separate them?** If you only check stop-losses on rebalance day (every 2 weeks), a stock that falls sharply on Tuesday won't be exited until the next rebalance — potentially a 10–20% additional loss. Daily stop-loss checking dramatically limits how much damage any single position can do. **Full block structure:** .. code-block:: text ┌─ Config ──────────────────────────────────────────────┐ │ Primary Interval: 1w │ Secondary Interval: 1d │ │ Slots: 10 │ Stop Loss: 7% │ └───────────────────────────────────────────────────────┘ ┌─ Trading Loop ────────────────────────────────┐ │ │ │ ┌─ Primary (1w) ───────────────────────────────┐ │ │ │ │ │ │ │ IF Index Value > SMA(200) │ │ │ │ → Rank by Momentum(189) │ │ │ │ → Cooldown Filter(20d) │ │ │ │ → Rebalance: Enter │ │ │ │ → Rebalance: Exit (old positions)│ │ │ │ │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ ┌─ Secondary (1d) ─────────────────────────────┐ │ │ │ Check Stop Loss (eod) │ │ │ └──────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────┘ ---- Three-timeframe example: Momentum with limit entries ----------------------------------------------------- This pattern adds a third interval to implement the "buy the dip" limit order logic: - **Primary (2w):** Rank stocks, schedule limit orders for next week. - **Secondary (1d):** Execute any pending limit orders; check stop-losses. - **Tertiary (2w):** Cancel unexecuted limit orders and start fresh. .. code-block:: text Config: Primary Interval: 2w Secondary Interval: 1d Tertiary Interval: 2w ┌─ Trading Loop ────────────────────────────────┐ │ │ │ ┌─ Primary (2w) ───────────────────────────────┐ │ │ │ IF Index > SMA(200) │ │ │ │ → Rank Momentum → Enter Next-Week Limit │ │ │ │ → Rebalance: Exit (old positions)│ │ │ └──────────────────────────────────────────────┘ │ │ │ │ ┌─ Secondary (1d) ─────────────────────────────┐ │ │ │ Execute Limit Orders │ │ │ │ Check Stop Loss (eod) │ │ │ └──────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────┘ **Why limit entries?** Instead of buying at the weekly close (which may be elevated after a strong week), you set a limit at 0.5–1% below the close. If the stock dips early in the following week, you get a better fill price. If it never dips, the order is not filled — you avoid chasing the position. ---- Using intervals for regime detection -------------------------------------- A fourth interval can implement a slower "regime check" — updating the market regime less frequently than the rebalance to avoid reacting to short-term noise: .. code-block:: text Config: Primary Interval: 2w (rebalance) Secondary Interval: 1d (stop-loss) Quaternary Interval: 1m (regime check — monthly) Monthly regime check logic: .. code-block:: text ┌─ Quaternary (1m) ────────────────────────────────┐ │ IF Index Value < Index Weekly Quantile(25) │ │ (index is in its lowest 25% historically) │ │ → Rebalance: Exit (exit everything) │ └──────────────────────────────────────────────────┘ This exits all positions if the market enters a deep bear regime (bottom 25% of all weekly closes), and stays out until the monthly check confirms recovery. ---- Interval timing reference --------------------------- When exactly does each interval fire? .. list-table:: :header-rows: 1 :widths: 15 85 * - Format - Fires on * - ``1d`` - Every trading day. * - ``2d`` - Every 2nd trading day from the strategy start date. * - ``1w`` - The first trading day of each calendar week (Monday, or next open day). * - ``2w`` - The first trading day of every other calendar week. * - ``1m`` - The first trading day of each calendar month. .. note:: Intervals are counted from the strategy's **Start Date**, not from today. A ``2w`` interval starting on a Wednesday will fire every other Wednesday throughout the test. ---- Common mistakes ---------------- **Mistake 1 — Checking stop-losses only on the rebalance interval** If Primary = ``2w`` and you put ``Check Stop Loss`` inside the Primary block, stop-losses are only evaluated every two weeks. A stock can fall 20% in the middle of a two-week period before being caught. Always place ``Check Stop Loss`` inside the **Secondary (1d)** block. **Mistake 2 — Executing limit orders on the rebalance day only** Limit orders need to be checked *daily* — otherwise they only trigger on rebalance day. Place ``Execute Limit Orders`` inside the **Secondary (1d)** block. **Mistake 3 — Conflicting enter/exit logic across intervals** If Primary enters positions and Secondary also contains entry logic, they may conflict — entering the same stock twice or fighting over slot allocation. Keep entry logic in **one interval** and risk management in another.