Appearance

Personalize your experience

Mode
Accent Color
Direction
Writing Strategies in the IDE

Strategies

IDE

Paste the code below into a new Strategy file. Click Run ▶ to backtest, then Apply to see trade markers on the chart.

⚡ Quick Start — Complete Working Strategy

python
"""SMA Crossover Strategy — Quatick Quick StartCopy, paste, Run ▶, Apply ✓"""import numpy as npMETADATA = { "id": "sma-cross", "name": "SMA Crossover", "version": "1.0.0" }DEFAULT_PARAMS = {    "fast": 9, "slow": 21,    "risk_pct": 2.0, "stop_atr": 1.5, "tp_atr": 3.0,    "initial_equity": 100000,}# ---- helpers ----------------------------------------------------------------def _sma(arr, n): return np.convolve(arr, np.ones(n)/n, 'full')[:len(arr)]def _atr(bars, n=14):    hi = np.array([b['high'] for b in bars])    lo = np.array([b['low']  for b in bars])    cl = np.array([b['close'] for b in bars])    tr = np.maximum(hi - lo, np.maximum(abs(hi - np.roll(cl, 1)), abs(lo - np.roll(cl, 1))))    tr[0] = hi[0] - lo[0]    atr = np.zeros(len(tr))    atr[n - 1] = np.mean(tr[:n])    for i in range(n, len(tr)):        atr[i] = (atr[i-1] * (n-1) + tr[i]) / n    return atr# ---- main entry point -------------------------------------------------------def run(bars: list, params: dict = None) -> dict:    p = {**DEFAULT_PARAMS, **(params or {})}    closes = np.array([b['close'] for b in bars])    fast   = _sma(closes, p['fast'])    slow   = _sma(closes, p['slow'])    atr    = _atr(bars)    signals   = []    equity    = p['initial_equity']    trades    = []    position  = None  # {side, entry, stop, tp, qty}    warmup = max(p['fast'], p['slow'])    for i in range(warmup, len(bars)):        bar  = bars[i]        time = bar['time']        cl   = closes[i]        a    = atr[i] if atr[i] > 0 else cl * 0.01        # --- manage open position ---        if position:            hit_stop = (position['side'] == 'long'  and cl <= position['stop']) or \                       (position['side'] == 'short' and cl >= position['stop'])            hit_tp   = (position['side'] == 'long'  and cl >= position['tp']) or \                       (position['side'] == 'short' and cl <= position['tp'])            if hit_stop or hit_tp:                pnl = (cl - position['entry']) * position['qty'] * (1 if position['side'] == 'long' else -1)                equity += pnl                trades.append({ 'pnl': pnl, 'side': position['side'] })                signals.append({ 'time': time, 'type': 'LONG_EXIT' if position['side'] == 'long' else 'SHORT_EXIT', 'price': cl })                position = None        # --- new entry signals ---        if not position:            golden = fast[i-1] <= slow[i-1] and fast[i] > slow[i]   # bullish crossover            death  = fast[i-1] >= slow[i-1] and fast[i] < slow[i]   # bearish crossover            if golden:                risk_amt = equity * p['risk_pct'] / 100                qty = max(1, int(risk_amt / (a * p['stop_atr'])))                position = { 'side': 'long', 'entry': cl, 'qty': qty,                             'stop': cl - a * p['stop_atr'], 'tp': cl + a * p['tp_atr'] }                signals.append({ 'time': time, 'type': 'LONG_ENTRY', 'price': cl })            elif death:                risk_amt = equity * p['risk_pct'] / 100                qty = max(1, int(risk_amt / (a * p['stop_atr'])))                position = { 'side': 'short', 'entry': cl, 'qty': qty,                             'stop': cl + a * p['stop_atr'], 'tp': cl - a * p['tp_atr'] }                signals.append({ 'time': time, 'type': 'SHORT_ENTRY', 'price': cl })    # close any open position at end    if position:        cl = closes[-1]        pnl = (cl - position['entry']) * position['qty'] * (1 if position['side'] == 'long' else -1)        equity += pnl        trades.append({ 'pnl': pnl, 'side': position['side'] })    wins = [t for t in trades if t['pnl'] > 0]    gross_p = sum(t['pnl'] for t in wins) if wins else 0    gross_l = abs(sum(t['pnl'] for t in trades if t['pnl'] <= 0)) or 1    return {        "signals": signals,        "performance": {            "total_trades":  len(trades),            "win_rate":      round(len(wins) / len(trades) * 100, 2) if trades else 0,            "profit_factor": round(gross_p / gross_l, 2),            "total_pnl":     round(equity - p['initial_equity'], 2),            "return_pct":    round((equity - p['initial_equity']) / p['initial_equity'] * 100, 2),        }    }
★
Pro tip:Workflow: set script type to Strategy → Run ▶ to backtest and see in the Output tab → Apply to draw buy/sell markers on the chart.

📂 Python SDK — Built-in Helpers

FunctionSignatureReturns
np.arraynp.array([b["close"] for b in bars]) float array of prices
np.convolvenp.convolve(arr, np.ones(n)/n, "full")Fast SMA via convolution
np.maximum / minimumnp.maximum(a, b)Element-wise max/min (, range calcs)
np.rollnp.roll(arr, 1)Shift array by 1 (yesterday vs today)
np.stdnp.std(arr[-n:]) of last n values
np.meannp.mean(arr[-n:])Mean of last n values
np.cumsumnp.cumsum(arr) sum ()
np.argmax / argminnp.argmax(arr)Index of max/min

📊 Signal Types Reference

Signal typeMeaningChart marker
LONG_ENTRYOpen a ▲ Green arrow below bar
LONG_EXITClose the ▼ Gray arrow above bar
SHORT_ENTRYOpen a ▼ Red arrow above bar
SHORT_EXITClose the ▲ Gray arrow below bar

Creating Trading Strategies

Strategies in Quatick define complete trading logic: when to enter and exit positions, how much capital to allocate, and how to manage risk. They combine one or more technical indicators with rule-based -making to generate actionable trading signals.

All strategies in Quatick are written in Python and run via the (WebAssembly Python) , giving you access to NumPy for high-performance numerical computation.

1. Strategy Architecture

A strategy script is a Python module that exports:

  • — Identity dict with id, name, version,
  • DEFAULT_PARAMS — Default parameter values the user can override
  • run(bars, params) — Main entry : processes all bars and returns signals + performance
  • Helper functions — sma(), (), (), etc. for technical calculations

2. Strategy Lifecycle

When a strategy is executed, the calls your run() function with the full bar dataset. The function iterates through each bar, evaluating conditions and generating signals:

python
# Strategy execution flow:## 1. INITIALIZATION#    - Load parameters, set initial equity, clear state## 2. BAR ITERATION (for each bar in the dataset)#    ├── Calculate indicator values (SMA, RSI, etc.)#    ├── Check ENTRY conditions (and generate LONG_ENTRY / SHORT_ENTRY)#    ├── Check EXIT conditions (stop loss, take profit, signal exit)#    ├── Update position P&L#    └── Record signal if generated## 3. PERFORMANCE CALCULATION#    - Compute win rate, profit factor, max drawdown, etc.#    - Return signals list + performance metrics

3. Signal Types

SignalActionDescriptionMarker
LONG_ENTRYBuyOpen a — profit from price increase▲ Green arrow below bar
LONG_EXITSellClose an existing ▼ Green arrow above bar
SHORT_ENTRYSell ShortOpen a — profit from price decrease▼ Red arrow above bar
SHORT_EXITBuy to CoverClose an existing ▲ Red arrow below bar
NoneNo trading action — conditions not metNo marker

4. Risk Management Parameters

Every professional strategy must implement proper risk management. These are the key parameters to define:

ParameterTypeDescriptionTypical Range
risk_percentfloatMaximum of equity to risk per trade0.5% – 3.0%
stop_loss_atrfloat distance as a multiple of 1.0 – 3.0
take_profit_atrfloatTake profit distance as a multiple of 2.0 – 6.0
max_positionsintMaximum number of simultaneous open positions1 – 5
cooldown_barsintMinimum bars to wait between 1 – 20
initial_equityfloatStarting account balance for $10,000 – $1,000,000
allow_shortsboolWhether the strategy can open short positionsTrue / False
max_drawdown_pctfloat switch — stop trading if exceeds this10% – 30%
trailing_stopboolWhether trails with True / False

5. Position Sizing Algorithms

Position sizing determines how many shares/contracts to trade per signal. Proper is critical for risk management.

5.1 Fixed Risk Position Sizing

python
def calculate_position_size(equity: float, risk_pct: float,                              entry_price: float, stop_price: float) -> int:    """    Risk-based position sizing.        Args:        equity: Current account equity        risk_pct: Risk per trade as percentage (e.g., 2.0 for 2%)        entry_price: Planned entry price        stop_price: Stop loss price        Returns:        Number of shares to trade        Example:        equity = $100,000        risk_pct = 2.0 (2%)        entry = $50.00        stop = $48.00                risk_amount = $100,000 × 0.02 = $2,000        risk_per_share = $50.00 - $48.00 = $2.00        quantity = $2,000 / $2.00 = 1,000 shares    """    risk_amount = equity * (risk_pct / 100)    risk_per_share = abs(entry_price - stop_price)        if risk_per_share <= 0:        return 0        quantity = int(risk_amount / risk_per_share)        # Never use more than 10% of equity in a single position    max_quantity = int((equity * 0.10) / entry_price)        return min(quantity, max_quantity)

5.2 Kelly Criterion Position Sizing

python
def kelly_position_size(win_rate: float, avg_win: float, avg_loss: float,                        equity: float, fraction: float = 0.5) -> float:    """    Kelly Criterion — optimal bet sizing based on historical performance.    Uses fractional Kelly (default 50%) for safety.        Kelly % = W - [(1 - W) / R]    where W = win rate, R = win/loss ratio    """    if avg_loss == 0:        return 0        win_loss_ratio = avg_win / avg_loss    kelly_pct = win_rate - ((1 - win_rate) / win_loss_ratio)        # Apply fraction (half Kelly is common for safety)    adjusted = kelly_pct * fraction        # Clamp between 0% and 25% of equity    return max(0, min(adjusted, 0.25)) * equity

6. Stop Loss Strategies

TypeDescriptionCode Pattern
Fixed ATR StopStop at N × below/above entrystop = entry - * multiplier
Percentage StopStop at N% below/above entrystop = entry * (1 - pct/100)
Trailing StopStop moves up with price, never downstop = max(stop, high - * N)
Chandelier Exit minus N × stop = max(highs[-22:]) - 3 *
Parabolic SAR-based trailing stopComplex — see SAR indicator
Support LevelStop below nearest support levelstop = find_support(bars, lookback)
python
# Trailing stop implementationdef update_trailing_stop(current_stop: float, current_high: float,                         atr_value: float, atr_mult: float,                         side: str) -> float:    """Move stop loss in profitable direction only."""    if side == "long":        new_stop = current_high - atr_value * atr_mult        return max(current_stop, new_stop)  # Only move UP    else:  # short        new_stop = current_high + atr_value * atr_mult        return min(current_stop, new_stop)  # Only move DOWN

7.1 Moving Average Crossover

python
"""Dual MA Crossover — The most classic strategy pattern.Entry:  Fast MA crosses ABOVE slow MA → LongExit:   Fast MA crosses BELOW slow MA → Close long"""def detect_crossover(fast_values, slow_values, index):    if index < 1:        return None        prev_fast, curr_fast = fast_values[index - 1], fast_values[index]    prev_slow, curr_slow = slow_values[index - 1], slow_values[index]        if prev_fast <= prev_slow and curr_fast > curr_slow:        return "GOLDEN_CROSS"   # Bullish    elif prev_fast >= prev_slow and curr_fast < curr_slow:        return "DEATH_CROSS"    # Bearish        return None

7.2 Mean Reversion (Bollinger Bands)

python
"""Mean Reversion — Price tends to return to the mean.Entry:  Price touches lower Bollinger Band → Long (oversold)Exit:   Price reaches middle band (SMA) or upper band"""def check_mean_reversion(close, sma, upper, lower):    if close <= lower:        return "LONG_ENTRY"   # Oversold — expect bounce    elif close >= upper:        return "SHORT_ENTRY"  # Overbought — expect pullback    elif close >= sma:        return "LONG_EXIT"    # Returned to mean    return None

7.3 Breakout Strategy

python
"""Breakout — Price breaks above resistance or below support.Entry:  Price > highest high of last N bars → Long        Price < lowest low of last N bars → ShortExit:   Trailing stop or opposite signal"""def check_breakout(bars, index, lookback=20):    if index < lookback:        return None        window = bars[index - lookback:index]    highest = max(b["high"] for b in window)    lowest = min(b["low"] for b in window)    current = bars[index]["close"]        if current > highest:        return "LONG_ENTRY"    # Upside breakout    elif current < lowest:        return "SHORT_ENTRY"   # Downside breakout    return None

7.4 RSI Divergence

python
"""RSI Divergence — Price makes new high but RSI doesn't (bearish)                 Price makes new low but RSI doesn't (bullish)"""def detect_divergence(prices, rsi_values, index, lookback=14):    if index < lookback * 2:        return None        recent_prices = prices[index - lookback:index + 1]    recent_rsi = rsi_values[index - lookback:index + 1]        price_higher_high = recent_prices[-1] > max(recent_prices[:-1])    rsi_lower_high = recent_rsi[-1] < max(recent_rsi[:-1])        price_lower_low = recent_prices[-1] < min(recent_prices[:-1])    rsi_higher_low = recent_rsi[-1] > min(recent_rsi[:-1])        if price_higher_high and rsi_lower_high:        return "BEARISH_DIVERGENCE"  # Potential SHORT    elif price_lower_low and rsi_higher_low:        return "BULLISH_DIVERGENCE"  # Potential LONG    return None

7.5 Multi-Timeframe Confirmation

python
"""Multi-Timeframe — Align signals across timeframes for confidence.Higher timeframe: Determine trend direction (bias)Lower timeframe: Find entry timing (execution)Example:   Daily chart → EMA 50 > EMA 200 → Bullish bias  4H chart → RSI crosses above 30 → Execute long entry"""def multi_tf_strategy(daily_bars, hourly_bars, index):    # Determine daily bias    daily_ema_fast = ema(daily_bars, 50)    daily_ema_slow = ema(daily_bars, 200)    bias = "bullish" if daily_ema_fast > daily_ema_slow else "bearish"        # Find entry on lower timeframe    hourly_rsi = rsi(hourly_bars, 14)        if bias == "bullish" and hourly_rsi < 30:        return "LONG_ENTRY"   # Oversold in an uptrend    elif bias == "bearish" and hourly_rsi > 70:        return "SHORT_ENTRY"  # Overbought in a downtrend    return None

8. Performance Metrics

After , evaluate your strategy with these :

MetricFormulaGood ValueWhat It Tells You
Wins / Total × 100> 50%How often are profitable
Gross Profit / Gross Loss> 1.5Dollars won per dollar lost
Peak-to-trough equity %< 20%Worst-case capital decline
Mean Return / > 1.0Risk-adjusted performance
Sortino RatioMean Return / Downside > 1.5Downside risk-adjusted performance
Calmar RatioAnnual Return / > 1.0Return relative to worst decline
(WR × AvgWin) - ((1-WR) × AvgLoss)> 0
Avg Trade Sum of durations / VariesHow long positions are
Recovery FactorNet Profit / > 3.0How quickly losses are recovered
python
def calculate_performance(trades: list, initial_equity: float) -> dict:    """Compute comprehensive performance metrics."""    if not trades:        return {"total_trades": 0, "win_rate": 0}        wins = [t for t in trades if t["pnl"] > 0]    losses = [t for t in trades if t["pnl"] <= 0]        total_pnl = sum(t["pnl"] for t in trades)    gross_profit = sum(t["pnl"] for t in wins) if wins else 0    gross_loss = abs(sum(t["pnl"] for t in losses)) if losses else 0        # Track equity curve for drawdown    equity = initial_equity    peak = equity    max_dd = 0    equity_curve = []        for trade in trades:        equity += trade["pnl"]        equity_curve.append(equity)        peak = max(peak, equity)        dd = (peak - equity) / peak * 100        max_dd = max(max_dd, dd)        return {        "total_trades": len(trades),        "win_rate": len(wins) / len(trades) * 100,        "profit_factor": gross_profit / gross_loss if gross_loss > 0 else float("inf"),        "total_pnl": total_pnl,        "max_drawdown": max_dd,        "avg_win": gross_profit / len(wins) if wins else 0,        "avg_loss": gross_loss / len(losses) if losses else 0,        "return_pct": (equity - initial_equity) / initial_equity * 100,        "largest_win": max((t["pnl"] for t in wins), default=0),        "largest_loss": min((t["pnl"] for t in losses), default=0),        "expectancy": total_pnl / len(trades),    }

9. Complete Strategy Template

python
"""Complete Strategy Template — Quatick IDECopy this template and modify the entry/exit logic."""import numpy as npMETADATA = {    "id": "my-strategy",    "name": "My Strategy",    "version": "1.0.0",    "description": "Description of what this strategy does",}DEFAULT_PARAMS = {    "fast_period": 9,    "slow_period": 21,    "rsi_period": 14,    "risk_percent": 2.0,    "stop_loss_atr": 1.5,    "take_profit_atr": 3.0,    "initial_equity": 100000,    "allow_shorts": True,    "cooldown_bars": 3,}# === Technical Indicators ===def sma(values, period):    """Simple Moving Average."""    if len(values) < period:        return float("nan")    return float(np.mean(values[-period:]))def ema(values, period):    """Exponential Moving Average."""    if len(values) < period:        return float("nan")    k = 2 / (period + 1)    result = np.mean(values[:period])    for v in values[period:]:        result = v * k + result * (1 - k)    return float(result)def atr(bars, period=14):    """Average True Range."""    if len(bars) < period + 1:        return float("nan")    trs = []    for i in range(-period, 0):        h, l, pc = bars[i]["high"], bars[i]["low"], bars[i-1]["close"]        trs.append(max(h - l, abs(h - pc), abs(l - pc)))    return float(np.mean(trs))def rsi(values, period=14):    """Relative Strength Index."""    if len(values) < period + 1:        return float("nan")    changes = np.diff(values[-period - 1:])    gains = np.where(changes > 0, changes, 0)    losses = np.where(changes < 0, -changes, 0)    avg_gain = np.mean(gains)    avg_loss = np.mean(losses)    if avg_loss == 0:        return 100.0    rs = avg_gain / avg_loss    return float(100 - (100 / (1 + rs)))# === Main Strategy Logic ===def run(bars: list[dict], params: dict | None = None) -> dict:    """Run the strategy on historical bar data."""    p = {**DEFAULT_PARAMS, **(params or {})}    closes = np.array([b["close"] for b in bars], dtype=float)        signals = []    equity = p["initial_equity"]    position = None    trades = []    last_trade_bar = -p["cooldown_bars"]    peak_equity = equity    max_drawdown = 0        for i in range(1, len(bars)):        bar = bars[i]                # === Calculate Indicators ===        fast_ma = sma(closes[:i+1], p["fast_period"])        slow_ma = sma(closes[:i+1], p["slow_period"])        prev_fast = sma(closes[:i], p["fast_period"])        prev_slow = sma(closes[:i], p["slow_period"])        current_rsi = rsi(closes[:i+1], p["rsi_period"])        current_atr = atr(bars[:i+1], 14)                if any(np.isnan(x) for x in [fast_ma, slow_ma, prev_fast, prev_slow]):            continue                # === Entry Logic ===        if position is None and (i - last_trade_bar) >= p["cooldown_bars"]:                        # LONG: Golden cross + RSI not overbought            golden_cross = prev_fast <= prev_slow and fast_ma > slow_ma            if golden_cross and (np.isnan(current_rsi) or current_rsi < 70):                stop = bar["close"] - p["stop_loss_atr"] * current_atr                tp = bar["close"] + p["take_profit_atr"] * current_atr                risk = bar["close"] - stop                qty = int(equity * (p["risk_percent"]/100) / risk) if risk > 0 else 0                                if qty > 0:                    position = {                        "side": "long", "entry": bar["close"],                        "time": bar["time"], "qty": qty,                        "stop": stop, "take_profit": tp,                    }                    signals.append({                        "time": bar["time"], "type": "LONG_ENTRY",                        "price": bar["close"], "reason": "Golden Cross",                    })                        # SHORT: Death cross + RSI not oversold            death_cross = prev_fast >= prev_slow and fast_ma < slow_ma            if death_cross and p["allow_shorts"] and (np.isnan(current_rsi) or current_rsi > 30):                stop = bar["close"] + p["stop_loss_atr"] * current_atr                tp = bar["close"] - p["take_profit_atr"] * current_atr                risk = stop - bar["close"]                qty = int(equity * (p["risk_percent"]/100) / risk) if risk > 0 else 0                                if qty > 0:                    position = {                        "side": "short", "entry": bar["close"],                        "time": bar["time"], "qty": qty,                        "stop": stop, "take_profit": tp,                    }                    signals.append({                        "time": bar["time"], "type": "SHORT_ENTRY",                        "price": bar["close"], "reason": "Death Cross",                    })                # === Exit Logic ===        if position:            price = bar["close"]            exit_reason = None                        if position["side"] == "long":                if price <= position["stop"]:                    exit_reason = "Stop Loss"                elif price >= position["take_profit"]:                    exit_reason = "Take Profit"                elif prev_fast >= prev_slow and fast_ma < slow_ma:                    exit_reason = "Signal Exit (Death Cross)"            else:                if price >= position["stop"]:                    exit_reason = "Stop Loss"                elif price <= position["take_profit"]:                    exit_reason = "Take Profit"                elif prev_fast <= prev_slow and fast_ma > slow_ma:                    exit_reason = "Signal Exit (Golden Cross)"                        if exit_reason:                pnl = (price - position["entry"]) * position["qty"]                if position["side"] == "short":                    pnl = -pnl                                equity += pnl                trades.append({                    "entry_time": position["time"],                    "exit_time": bar["time"],                    "side": position["side"],                    "entry_price": position["entry"],                    "exit_price": price,                    "qty": position["qty"],                    "pnl": pnl,                    "reason": exit_reason,                })                signals.append({                    "time": bar["time"],                    "type": f"{position['side'].upper()}_EXIT",                    "price": price,                    "reason": exit_reason,                })                position = None                last_trade_bar = i                                # Track drawdown                peak_equity = max(peak_equity, equity)                dd = (peak_equity - equity) / peak_equity * 100                max_drawdown = max(max_drawdown, dd)        # === Calculate Performance ===    wins = [t for t in trades if t["pnl"] > 0]    return {        "signals": signals,        "total_trades": len(trades),        "win_rate": len(wins) / len(trades) * 100 if trades else 0,        "profit_factor": (            sum(t["pnl"] for t in wins) /            abs(sum(t["pnl"] for t in trades if t["pnl"] <= 0))            if any(t["pnl"] <= 0 for t in trades) else float("inf")        ) if wins else 0,        "total_pnl": sum(t["pnl"] for t in trades),        "max_drawdown": max_drawdown,        "final_equity": equity,        "return_pct": (equity - p["initial_equity"]) / p["initial_equity"] * 100,    }if __name__ == "__main__":    sample = [        {"time": i, "open": 100 + np.sin(i/5) * 10,         "high": 105 + np.sin(i/5) * 10,         "low": 95 + np.sin(i/5) * 10,         "close": 100 + np.sin(i/5) * 10, "volume": 1000}        for i in range(200)    ]    result = run(sample)    print(f"Trades: {result['total_trades']}")    print(f"Win Rate: {result['win_rate']:.1f}%")    print(f"Total PnL: {result['total_pnl']:.2f}")    print(f"Return: {result['return_pct']:.2f}%")
!
Caution:Always test your strategy on multiple market conditions: trending up, trending down, sideways/range-bound, and high-volatility periods. A strategy that only works in one market condition will fail in production.

10. Debugging Tips

  • Use print() statements to trace signal generation — output appears in Console tab
  • Start with a simple strategy and add incrementally
  • Verify indicator calculations manually against known-good sources ()
  • Check for : ensure no is used in decisions
  • Watch for survivorship bias: test on that includes delisted securities
  • Log trade reasons to understand why each trade was taken
  • performance across different parameter values to assess robustness
  • If is suspiciously high (>80%), you likely have a bug or

Related articles

  • Step 6 — Exit & Risk

    Automation / Strategy Builder / Wizard Steps

    Exit conditions, stop loss, take profit, staged partial exits and portfolio-level limits. The step that decides whether a losing trade costs you a percent…

  • Strategy DSL — Execution Model

    Coding / Strategy DSL

    What the engine does on every bar: protective exits, exit signals, entries, layers and re-entries, sizing and costs, and where every statistic in the result…

  • DCA Take Profit

    Automation / Predefined Strategies / DCA Bot

    Target = average × (1 ± TP). Moves toward the market as safety orders fill, so a small bounce closes the cycle.

  • Grid Range

    Charts / Drawing Tools / Measurement

    Design a grid trading ladder directly on the chart. Drag out the price range the grid should trade and the tool derives every rung price, order size,…

  • Arrow Marker

    Charts / Drawing Tools / Annotation

    A directional arrow pointing at a specific chart element. Arrow markers are used to indicate entry and exit points, highlight bars of interest, and draw…

  • ATR Channel

    Charts / Drawing Tools / Channels

    A least-squares trend line with boundaries a multiple of average true range away on each side. A volatility channel over a range you select — it answers how…

  • Built-in Indicators & Overlays

    Coding / IDE / Reference

    Quatick ships with a full library of pre-built indicators and overlays. You can use these out of the box, or study their implementations as reference for…

  • DCA Modes

    Automation / Predefined Strategies / DCA Bot

    How safety-order sizes grow with depth — and how cycles open.

  • DCA Stop Loss

    Automation / Predefined Strategies / DCA Bot

    When armed, the engine checks every tick: once price moves the stop distance against the cycle's average entry , it cancels the resting safety orders and…

Browse all knowledge base articles →