Price Change Trigger
The price_change trigger fires when the market price has moved by a specified percentage over a lookback window. It compares the current candle's close to a candle from N minutes ago. This trigger is global — it does not require an open position.
Use it for momentum entries ("buy after a 5% dip in the last 4 hours") or breakout detection ("price is up 3% over the last day").
For price changes relative to your position's entry price, see Position Price Change instead. price_change watches the market; pos_price_change watches your P&L.
TOML Syntax
[[actions.triggers]]
type = "price_change"
value = "-5%" # Required: ±N% threshold
timeframe = "1h" # Optional: candle size (default: 1m)
lookback = 24 # Optional: number of candles to look back (default: 1)
max_value = "-15%" # Optional: maximum allowed change (range cap)
max_count = 1 # Optional: max fires per position
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | Yes | — | Must be "price_change" |
value | string | Yes | — | Percentage threshold in "±N%" format |
timeframe | string | No | "1m" | Candle size for the lookback window |
lookback | integer | No | 1 | Number of timeframe-sized candles to look back |
max_value | string | No | — | Maximum change in "±N%" format (caps the range) |
max_count | integer | No | unlimited | Maximum times this trigger can fire per position |
How It Works
The engine computes a total lookback in 1-minute candles:
total_lookback = lookback × timeframe_in_minutes
timeframe | lookback | Total 1m candles | Real window |
|---|---|---|---|
"1h" | 1 (default) | 60 | 1 hour |
"1h" | 4 | 240 | 4 hours |
"1h" | 24 | 1440 | 24 hours |
"4h" | 6 | 1440 | 24 hours |
"1d" | 1 (default) | 1440 | 1 day |
"5m" | 12 | 60 | 1 hour |
When lookback is omitted, it defaults to 1 — meaning the window equals exactly one timeframe period. This is backwards-compatible with the original behavior.
The engine then calculates:
change_pct = (current_close - close_N_candles_ago) / close_N_candles_ago × 100
- Negative
value(e.g.,"-5%"): trigger fires whenchange_pct <= -5.0 - Positive
value(e.g.,"+3%"): trigger fires whenchange_pct >= 3.0
graph TD
A["Current candle close"] --> C{"Calculate % change<br/>over lookback window"}
B["Close from N candles ago<br/>(N = lookback × timeframe)"] --> C
C --> D{"change meets<br/>threshold?"}
D -->|Yes| E{"Within max_value<br/>range?"}
D -->|No| F["No action"]
E -->|Yes or no max_value| G["Trigger fires"]
E -->|No — too extreme| F
The value Format
The value field uses a "±N%" string format:
| Value | Meaning |
|---|---|
"-5%" | Price dropped at least 5% |
"-2.0%" | Price dropped at least 2% |
"+3%" | Price rose at least 3% |
"+1.5%" | Price rose at least 1.5% |
"3%" | Same as "+3%" (positive assumed) |
The lookback Parameter
The lookback parameter controls how many timeframe-sized candles to look back. Without it, the engine looks back exactly one timeframe period.
# Without lookback: compares to 1 hour ago
type = "price_change"
value = "-5%"
timeframe = "1h"
# With lookback: compares to 24 hours ago (24 × 1h)
type = "price_change"
value = "-5%"
timeframe = "1h"
lookback = 24
This is useful when you want a long lookback window but the timeframe options don't cover it directly. For example, "did the price drop 10% over the last 3 days?" can be expressed as:
type = "price_change"
value = "-10%"
timeframe = "1d"
lookback = 3
The max_value Parameter (Range Capping)
max_value caps how extreme the price change can be for the trigger to fire. It creates a range instead of a simple threshold — useful for avoiding "falling knife" entries.
# Fire when price drops between 5% and 15%
# (skip if it dropped MORE than 15% — that's a falling knife)
type = "price_change"
value = "-5%"
max_value = "-15%"
timeframe = "4h"
How it works:
- For negative thresholds:
valueis the minimum drop,max_valueis the maximum drop - For positive thresholds:
valueis the minimum rise,max_valueis the maximum rise
value | max_value | Fires when change is... |
|---|---|---|
"-5%" | "-15%" | Between -5% and -15% |
"-5%" | (none) | -5% or worse (no cap) |
"+3%" | "+10%" | Between +3% and +10% |
"+3%" | (none) | +3% or better (no cap) |
max_value works with all price-change family triggers: price_change, price_change_from_high, and price_change_from_low.
Valid Timeframes
The timeframe field accepts: 1m, 5m, 15m, 1h, 4h, 1d.
When omitted, the trigger uses 1m — meaning it compares the current close to the close 1 minute ago. This is rarely useful on its own. In practice, you almost always want a larger timeframe.
Examples
Buy After a 5% Dip Over 4 Hours
[[actions]]
type = "open_long"
amount = "100 USDC"
[[actions.triggers]]
type = "price_change"
value = "-5%"
timeframe = "4h"
Buy After a 10% Dip Over 24 Hours (With Lookback)
[[actions]]
type = "open_long"
amount = "200 USDC"
[[actions.triggers]]
type = "price_change"
value = "-10%"
timeframe = "1h"
lookback = 24
Sell After a 3% Rise Over 1 Hour
[[actions]]
type = "sell"
amount = "100%"
[[actions.triggers]]
type = "price_change"
value = "+3%"
timeframe = "1h"
DCA Entry on Hourly Dip (Fire Once)
[[actions]]
type = "buy"
amount = "100 USDC"
average_price = true
[[actions.triggers]]
type = "price_change"
value = "-3%"
timeframe = "1h"
max_count = 1
Buy the Dip — But Not the Crash (Range Cap)
# Enter on 5-15% dips over 4 hours, skip if it's a free fall
[[actions]]
type = "open_long"
amount = "100 USDC"
[[actions.triggers]]
type = "price_change"
value = "-5%"
max_value = "-15%"
timeframe = "4h"
Combine with Technical Indicator
# Buy when price dropped 3% in the last hour AND RSI is oversold
[[actions]]
type = "open_long"
amount = "100 USDC"
[[actions.triggers]]
type = "price_change"
value = "-3%"
timeframe = "1h"
[[actions.triggers]]
indicator = "rsi_14"
operator = "<"
target = "30"
timeframe = "1h"
Tips
price_change is a global market signal. It works whether or not you have an open position. This makes it ideal for entry triggers that watch for market-wide dips or rallies.
Use lookback when standard timeframes don't cover the window you need. timeframe = "1h" with lookback = 24 gives you a 24-hour window calculated from hourly candle boundaries.
max_value is your safety net. In volatile markets, a 5% dip might be normal — but a 30% crash could signal something fundamentally wrong. Use max_value to filter out extreme moves.
Without a timeframe, price_change compares to just 1 minute ago, which is extremely noisy. Always set a timeframe for meaningful signals.
Related Triggers
| Trigger | What It Measures |
|---|---|
| Price Change from High | % drop from the highest price in a lookback window |
| Price Change from Low | % rise from the lowest price in a lookback window |
| Position Price Change | % change from your entry price |
| Trailing Stop | % drop from position's peak price |
| Consecutive Candles | Streaks of red or green candles |