The PolyClaw Trading signal engine computes five deterministic indicators from pseudo-OHLC candle data using only the Python standard library. All implementations live inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/deniszidbaev-cmyk/polyclaw-trading/llms.txt
Use this file to discover all available pages before exploring further.
src/polyclaw_engine/indicators.py and are tested at exact boundary values. The 5m candle series is used for execution decisions; the 15m series is used for confirmation. Only candles with "complete": true are passed to indicator functions.
Parameter reference
| Indicator | Parameter | Env var | Default |
|---|---|---|---|
| EMA (fast) | period | EMA_FAST_PERIOD | 8 |
| EMA (slow) | period | EMA_SLOW_PERIOD | 21 |
| RSI | period | RSI_PERIOD | 14 |
| ATR | period | ATR_PERIOD | 14 |
| Realized volatility | lookback | (hardcoded) | 20 |
| POC bin size | bin_size | POC_BIN_SIZE | 0.01 |
| EMA trend min spread | min_spread | MIN_EMA_SPREAD_PCT | 0.003 (0.3%) |
| EMA overextension cap | max_extension | MAX_EMA_EXTENSION_ATR | 2.0 ATR |
| Bullish RSI range | [min, max] | BULLISH_RSI_MIN / BULLISH_RSI_MAX | [52, 72] |
| Bearish RSI range | [min, max] | BEARISH_RSI_MIN / BEARISH_RSI_MAX | [28, 48] |
| RSI overbought | threshold | RSI_OVERBOUGHT | 75 |
| RSI oversold | threshold | RSI_OVERSOLD | 25 |
EMA — Exponential Moving Average
The EMA uses the first observation in the series as its seed value. Every subsequent value applies the standard exponential smoothing formula. There is no warm-up period beyond the seed: the series is defined from the very first observation. Formula:indicators.py):
ema() convenience function returns the final value in the series, or None if the input is empty.
Default periods: EMA8 (EMA_FAST_PERIOD=8) for execution; EMA21 (EMA_SLOW_PERIOD=21) for trend confirmation.
EMA trend detection
A bullish EMA trend requires EMA8 to be above EMA21 by at leastMIN_EMA_SPREAD_PCT (default 0.003, i.e., 0.3%). A bearish trend requires EMA8 to be below EMA21 by the same minimum spread:
EMA overextension
If the close price is more thanMAX_EMA_EXTENSION_ATR (default 2.0) ATR units away from EMA21, the decision is flagged as overextended and an overextension_penalty is applied to the confidence score. Overextension also becomes a blocking reason that forces a HOLD.
RSI — Relative Strength Index
RSI uses Wilder’s recursive smoothing. The firstperiod deltas are averaged arithmetically to seed the smoothed average gain and loss. All subsequent updates use Wilder’s smoothing formula.
Formula:
period + 1 input values is required; None is returned if fewer values are available.
Python implementation (indicators.py):
RSI thresholds
RSI participates in both direction detection and signal scoring:| Purpose | Env var | Default |
|---|---|---|
| Bullish zone minimum | BULLISH_RSI_MIN | 52 |
| Bullish zone maximum | BULLISH_RSI_MAX | 72 |
| Bearish zone minimum | BEARISH_RSI_MIN | 28 |
| Bearish zone maximum | BEARISH_RSI_MAX | 48 |
| Overbought guard | RSI_OVERBOUGHT | 75 |
| Oversold guard | RSI_OVERSOLD | 25 |
0.0 outside the range.
ATR — Average True Range
ATR uses the same Wilder recursive smoothing as RSI. The firstperiod true ranges are averaged arithmetically to seed the smoothed ATR. A minimum of period candles is required.
True range formula:
indicators.py):
POC — Point of Control
The POC is the price bin with the highest public observation density, not traded volume. It provides context for price clustering and can add a small bonus to the confidence score (poc_context component, weight 0.05), but it never creates a directional signal on its own.
Algorithm:
POC_BIN_SIZE default is 0.01. The function returns None if the input is empty or the bin size is <= 0.
A price is considered “near POC” if:
The POC implementation uses public API price-history observation counts, not exchange order-book volume. It is sample-density context only and is explicitly documented as such in
btc_strategy_engine.md.Realized Volatility
Realized volatility is the population standard deviation of the most recent 20 simple close-to-close returns. It is used as a market-quality and context signal rather than as a direct trading threshold. Formula:0.0 is returned if fewer are available.
Python implementation (indicators.py):
clamp utility
Theclamp function is used throughout the scoring and penalty logic to keep all confidence values inside [0.0, 1.0]:
indicators.py and used directly by the signal stage to bound the raw score after penalties.
Candle geometry helpers
The following helpers are also defined inindicators.py and used by the pattern engine:
| Function | Returns |
|---|---|
candle_body(candle) | abs(close - open) |
upper_wick(candle) | max(0, high - max(open, close)) |
lower_wick(candle) | max(0, min(open, close) - low) |
average_geometry(candles, lookback=20, exclude_current=True) | Dict of mean body, upper_wick, lower_wick over the lookback window |
percentage_distance(value, reference) | (value - reference) / reference, or None if reference is 0 or None |