Skip to content

05 · Strategy Coding in Practice

Five complete strategy examples, simple to advanced: dual MA trend, Bollinger Band mean reversion, RSI overbought/oversold, crypto grid trading, and a statistical arbitrage prototype. Each one explains core logic, gives a code skeleton, and marks applicable markets and risks — closing with parameter boundaries, portfolio thinking, and a personal roadmap.

Disclaimer: All content on this site is for learning and research only and does not constitute investment advice. Markets are risky; invest with caution.


Strategy Overview

#StrategyTypeApplicable MarketsDifficultyCore Return Source
Dual MA trendTrend followingFutures, crypto, major stocksRide medium/long trends, cut losses early
Bollinger mean reversionRange reversalStocks, ETFs, crypto spot★★Prices revert after deviating
RSI overbought/oversoldRange reversalInstruments with stable ranges★★Extreme sentiment reverts
Grid tradingRanging marketsCrypto spot (best for automation)★★Repeatedly harvest range oscillation
Stat arb prototypePairs/market-neutralCorrelated pairs (same-sector stocks, major coin pairs)★★★Spreads converge after diverging

1. Dual Moving Average Trend (Classic Entry)

Core logic: go long when the fast (short) MA crosses above the slow (long) MA; exit/short on the cross down. Eats trends, endures chop.

Python snippet (full backtest in 03-Your First Backtest; teaching example only, live-trading risk is yours):

python
import pandas as pd

def dual_ma_signal(df, fast=5, slow=20):
    df = df.copy()
    df["ma_fast"] = df["close"].rolling(fast).mean()
    df["ma_slow"] = df["close"].rolling(slow).mean()
    df["signal"] = (df["ma_fast"] > df["ma_slow"]).astype(int)
    df["position"] = df["signal"].shift(1)   # effective next day; prevents look-ahead bias
    return df
  • Applicable markets: markets with clear trending cycles (commodity futures, major crypto, broad indices).
  • Risks: whipsawed repeatedly in ranging markets (false breakouts); long drawdown periods feel awful; natural win rate is only 30-40% — it wins via the profit/loss ratio, and you'll fail if you can't hold.

2. Bollinger Band Mean Reversion (Range)

Core logic: price breaking the lower band signals oversold → buy; breaking the upper band signals overbought → sell/short; reverting to the middle band is the take-profit target.

Python snippet:

python
def boll_revert_signal(df, n=20, k=2.0):
    df = df.copy()
    df["mid"] = df["close"].rolling(n).mean()
    std = df["close"].rolling(n).std()
    df["upper"], df["lower"] = df["mid"] + k * std, df["mid"] - k * std
    df["signal"] = 0
    df.loc[df["close"] < df["lower"], "signal"] = 1    # buy at lower band
    df.loc[df["close"] > df["upper"], "signal"] = -1   # sell at upper band
    return df
  • Applicable markets: instruments that oscillate in ranges (stable-volatility stocks, sideways crypto spot).
  • Risks: catching falling knives in one-way moves — when price keeps sliding below the lower band, mean reversion just buys deeper into losses. You must pair it with a hard stop-loss (e.g., exit if price deviates another X% beyond the mid band) and confirm the instrument is actually ranging (check whether historical volatility is contracting first).

3. RSI Overbought/Oversold (Range Variant)

Core logic: RSI (Relative Strength Index) measures up/down momentum; >70 is overbought, <30 oversold — trade against the extreme.

Python snippet:

python
def rsi(close, n=14):
    diff = close.diff()
    up = diff.clip(lower=0).rolling(n).mean()
    down = (-diff.clip(upper=0)).rolling(n).mean()
    rs = up / down
    return 100 - 100 / (1 + rs)

def rsi_signal(df, over=70, under=30):
    df = df.copy()
    df["rsi"] = rsi(df["close"])
    df["signal"] = 0
    df.loc[df["rsi"] < under, "signal"] = 1      # buy oversold
    df.loc[df["rsi"] > over, "signal"] = -1      # sell overbought
    return df
  • Applicable markets: similar to Bollinger; prefers instruments with stable ranges. On high-volatility crypto, widen thresholds (e.g., 25/75) and watch for "RSI fade".
  • Risks: in strong trends RSI pins in overbought territory (bulls) or oversold territory (bears) for extended periods, and fading it gets run over by the trend. Fundamentally the same species as strategy ② — don't run two isomorphic range strategies heavily at once.

4. Grid Trading (Crypto Spot Automation)

Core logic: preset multiple order levels inside a price band — buy at each level as price falls, sell as it rises, harvesting oscillation repeatedly. Naturally suited to programs: orders rest all day, no direction prediction needed.

Order-loop sketch (teaching example only; live-trading risk is yours):

python
import time
from binance.spot import Spot

GRID_LO, GRID_HI = 55000, 75000   # grid range (reset per market; fictional example values)
GRID_STEP = 500                   # grid spacing
BASE_QTY = "0.01"                 # quantity per level (validate min qty & step size first)

def build_grid():
    """Generate all grid prices within the range"""
    prices = []
    p = GRID_LO
    while p <= GRID_HI:
        prices.append(round(p, 2))
        p += GRID_STEP
    return prices

def run_grid(client, symbol="BTCUSDT"):
    grid = build_grid()
    while True:
        # 1. Fetch existing open orders, compare with theoretical grid, fill missing levels
        open_orders = client.get_open_orders(symbol=symbol)
        price_set = {float(o["price"]) for o in open_orders}
        # 2. Grid levels without resting orders → place limit buys
        for price in grid:
            if price in price_set:
                continue
            client.new_order(symbol=symbol, side="BUY", type="LIMIT",
                             timeInForce="GTC", price=str(price),
                             quantity=BASE_QTY)
        # 3. Fills arrive via WebSocket/polling; trigger "sell this level" and re-post
        time.sleep(5)   # polling interval within rate limits

if __name__ == "__main__":
    client = Spot(api_key=os.environ["BINANCE_API_KEY"],
                  api_secret=os.environ["BINANCE_API_SECRET"])
    run_grid(client)
  • Applicable markets: crypto spot (7×24 + no price limits + free API) is grid heaven; don't force spot-style grids onto futures or contracts carrying funding rates.
  • Risks: ① in a one-way crash every level fills into losses and capital usage grows without bound → hard grid bounds and a capital cap are mandatory; ② in a one-way rally you sell out one level at a time and get left behind → set a top-line flatten rule; ③ a grid is a "range extractor" — once the range breaks, the strategy fails, so keep monitoring whether price stays inside.

5. Statistical Arbitrage Prototype (Pairs Trading)

Core logic: find two instruments that move together long-term (same-sector stocks, BTC vs a major alt); short the rich leg / long the cheap leg when the spread deviates from its historical mean, close when the spread converges — earning relative movement (market-neutral).

📖 Cointegration Concept

The core of pairs isn't "prices correlated" but "cointegrated" — whether the spread series oscillates around a stable mean. Use statsmodels for the cointegration test (teaching example only):

python
import numpy as np
from statsmodels.tsa.stattools import coint

# a, b are two aligned price series
def zscore(s):
    return (s - s.mean()) / s.std()

def pair_spread(a, b):
    s = a - b                                  # simple spread (regression residual also works)
    z = zscore(s)
    return z

# Cointegration test: p-value < 0.05 suggests cointegration → pairable
_, pvalue, _ = coint(a, b)
print("cointegration p-value:", pvalue)

# Trading rule: z > 1.5 short the spread (sell a, buy b); z < -1.5 reverse; |z| < 0.5 close
  • Applicable markets: same-sector/theme stock pairs, tightly correlated crypto pairs (BTC/ETH), ETFs vs constituents.
  • Risks: ① the spread relationship can fail (no longer converges after fundamentals change) — monitor zscore statistics dynamically and stop when it breaks; ② shorting China A-shares requires margin lending access — individuals should start with crypto spot pairs or long-leg-only simulations; ③ capacity and pair count are limited — don't over-lever.

6. Parameters and Failure Boundaries per Strategy

StrategyTypical Starting ParamsUnsuitable RegimesFailure Signature
Dual MAfast=5~20, slow=20~60Long sideways driftsString of small losses; drawdown hugging the stop line indefinitely
Bollingern=20, k=2.0One-way trendsStops triggering constantly; losses concentrated in trend segments
RSIn=14, 30/70Strong trends (fade)RSI pinned above 70 / below 30 for long stretches
GridRange at recent highs/lowsTrends that break the rangePrice escapes the range; trapped-capital ratio exceeds limit
Pairsz thresholds 1.5/0.5Correlation breakdownsSpread never reverts; cointegration p-value rises markedly

⚠️ Universal Boundary Discipline

  • Validate any strategy's parameters out-of-sample (see 03-Your First Backtest §7); high parameter sensitivity = unreliable;
  • Pre-write "stop conditions" for each strategy: disable at X% drawdown, review immediately on failure signatures — never white-knuckle it;
  • A strategy spec sheet (applicable regimes, failure signatures, stop conditions) matters as much as the research code.

7. Portfolio Thinking

Every single-strategy equity curve suffers from "makes nothing in bulls, loses in bears". The core of combining strategies is low correlation:

Combination MethodEffectExample
Multi-marketTrend/range cycles staggered across marketsCrypto trend + commodity trend
Multi-typeTrend and mean reversion naturally complement (one earns in trends, one in ranges)Dual MA + Bollinger
Multi-instrumentSingle-instrument event risk dilutedRun one strategy across 3-5 major coins
  • Validation: plot daily return series of all strategies together and inspect the correlation matrix; pairs correlating above 0.7 add no diversification;
  • Target: combined max drawdown below the worst single strategy — but note: portfolios don't stack expected returns; they reduce volatility, they don't amplify returns.

💡 What Actually Pays Is Detect-Maintain-Iterate

Writing strategy code takes days; keeping it alive takes continuous investment. What actually pays is the detect-maintain-iterate process you build around your strategies — that's the core competency of lasting personal quant. One pretty backtest curve is a starting point for research, not an asset.

8. The Reality of "20% Code, 80% Maintenance"

Writing strategy code takes days; keeping it alive takes continuous investment:

Maintenance ItemFrequencyContent
Data correctionsAd hocSource changes, refetching bad history; version your data
API changesWith each exchange updateBinance/OKX changing fields or rate limits; scripts must keep up
Market regime shiftsOngoingThe environment a strategy needs changes; failure detection must always run
Platform termsAnytimeCrypto platform ToS and regional restriction changes
Parameter reviewsMonthlyRolling-window reassessment of whether parameters still sit in their effective region

💡 Mindset Correction

A single backtest's "pretty curve" is a research starting point, not an asset. What actually pays is the detect-maintain-iterate process you build around strategies — the core competency of personal quant done long-term.


9. Personal Quant Roadmap

text
Week 1       Get a backtest running: toolchain + data + first dual MA backtest (articles 01-03 here)

Month 1      Build consistency: 2-3 strategies pass out-of-sample validation with experiment logs

Month 3      Paper trading: full pipeline simulated (or signal push + logging), at least 100 recorded signals

Small live capital: money whose total loss wouldn't affect your life, run 3+ months

Iterate continuously: monthly review → failure detection → new strategy research → gradual sizing

Each stage has explicit promotion criteria: paper stage requires "complete signal records, bug-free execution" before small capital; small-capital stage requires "controlled drawdowns, no major operational incidents" before adding funds. Those who skip stages always pay tuition at the next one.


⚠️ Risk Warning

All five strategies here are teaching examples: parameters are starting points, not answers; past returns do not represent future performance; any strategy can fail and lose money. Grid and pairs risks amplify quickly in extreme markets (one-way range breaks, non-converging spreads); automating execution adds rate limits, disconnects, and API changes as real loss sources. Always complete out-of-sample validation, set stop conditions, and verify long-term on paper and small capital before scaling. Historical data, backtest results do not guarantee future performance. This article is for learning and research only and does not constitute investment advice; execution details involving live trading and compliance follow latest regulations and platform docs.

Further Reading

For study and research only — not investment advice. Markets are risky.