Skip to content

Configuration reference ​

Every knob the bot obeys lives in one TOML file. Key facts before the tables:

  • Runtime config lives under data/ (data/config.toml, or wherever FARMER_CONFIG_PATH points — /app/data on Railway). The repo's config.toml is only a template copied on first run. Edit the runtime copy (or use dashboard Settings), never the tracked file.
  • Hot-reload: changes apply within seconds while the bot runs — no restart. A file that fails to parse is ignored and the previous config stays active.
  • Dashboard Settings → Bot settings writes these same keys, and Settings profiles apply curated packs of them.
  • Defaults below are the shipped template values. Several were deliberately tightened from the original spec after live trading (noted where interesting).

Don’t casually weaken stops, brakes, or vetting gates — they exist because the alternatives lost money. Change with evidence. See Risk & sizing.

[scanner] ​

KeyDefaultMeaning
interval_s60Seconds between scanner sweeps
pages3Meteora datapi pages per sweep (100 pools/page)
datapi_concurrency4Max datapi requests in flight. Sweep pages and majors whitelist lookups are independent round-trips that used to run one at a time, so a sweep paid the sum of their latency. Page 1 is still fetched alone — its page count sizes the rest
copycat_ignore_h24Losers of symbol dedupe ignored this long (hours)
sibling_tvl_tie_pct25Among a token's gate-passing pools, the deepest wins; fee/TVL breaks ties only within this % of the deepest pool's TVL. Replaces "highest fee/TVL", which structurally picked the thinnest sibling — thin pools earn less and their TVL swings 40–50% on ordinary LP moves, which P0 tvl_drain reads as a rug
retain_skipped_days30Prune skipped decision rows older than this (hourly). entered/exited rows — the audit trail — are never pruned. Nothing pruned these before; a Railway volume hit 83% inside a day. A rejection that repeats every sweep is stored as one row per 6-hour episode with a sweeps count, so 30 days now fits where a few hours used to
retain_snapshots_days3Prune pool_snapshots older than this. Only the latest row per pool is read; the rest was an offline replay dataset. Every ~300-row sweep lands here — at one sweep a minute, 3 days is ~1.3M rows (~245 MB), more than the default db_max_mb by itself. 1 keeps it near 80 MB
db_max_mb200Hard ceiling on farmer.db: above it, rows are trimmed oldest-first regardless of age — snapshots first, skip rows only once no snapshot is left to take, so the rejection history survives the ceiling. The hourly VACUUM briefly needs about the database's size again in free space, so keep this under ~40% of your volume — on a 1 GB Railway volume, 400 MB peaked at 92%

[gates] — pool hard gates ​

KeyDefaultMeaning
tvl_min_usd5000Minimum pool TVL
tvl_max_usd2000000Maximum pool TVL (above: fees too diluted)
mcap_min_usd100000Hard market-cap floor
mcap_micro_max_usd200000$100–200k mcap routes to the micro sleeve
mcap_micro_score_min75Micro needs a higher score than the normal 60 floor
min_entry_score60Skip any entry whose final score is below this (score_min). 60 = the sizing floor, so no change until raised
micro_tvl_min_usd15000Stricter TVL floor for micro only
micro_max_pool_share_pct10Micro position may not exceed this % of pool TVL
micro_size_mult0.5Micro sizes at half the core Kelly size
micro_max_position_sol0.45Absolute micro position cap
micro_max_slots1At most one micro position at a time
micro_deploy_cap_pct5Max % of wallet in open micro positions
young_max_age_min180Tokens younger than this (mint age; pool age if unknown) get the young-token cut
young_size_mult0.5Young-token / whale-overhang size multiplier (not compounded with micro's)
young_max_position_sol0.45Absolute cap on a risk-cut entry; risk-cut entries never get a tranche
whale_check_enabledtrueOne GMGN holders read per entry vs token-wide liquidity. No GMGN key → skipped
whale_fresh_hold_min180A "fresh" wallet first bought within this many minutes
whale_fresh_min_supply_pct2...and holds at least this % of supply (to count as a fresh whale)
whale_fresh_min_profit_mult1.5...and its holdings are worth at least this multiple of their cost
whale_skip_liquidity_frac0.25Skip when one fresh whale's holdings are worth ≥ this share of liquidity
whale_cut_fresh_overhang_frac0.25Young-token cut when fresh wallets' paper profit is ≥ this share of liquidity
fee_tvl_24h_min_pct20Min 24h fee/TVL, %/day
fee_tvl_30m_daily_min_pct10Min 30m fee/TVL annualized to daily, %/day
vol_30m_min_usd25000Min 30-minute volume
vol_trend_min0.8vol_1h / (vol_24h/24) floor — not in freefall
base_fee_min_pct / base_fee_max_pct0.2 / 5.0Base-fee band; >5% pools are arb-only
bin_step_min_new80Min bin step for tokens < 7 days old
fee_collection"prefer_quote"prefer_quote (bonus for SOL-only fee pools), quote_only, both_only, or any
quote_mintsSOL mintAllowed quote tokens (SOL only in meme mode)
price_divergence_max_pct2.0Max pool price vs Jupiter quote divergence
max_pool_share_pct20Skip if our position would exceed this % of pool TVL

[vetting] — token hard gates ​

Master switches (also in Settings UI) — off skips that hard fail; thresholds apply when on:

KeyDefaultMeaning
age_min_enabledtrueBlock "too young" (mint age: RugCheck detectedAt, then Jupiter createdAt, pool age only as a last resort)
age_max_enabledfalseBlock "too old". Off by default — the fee/volume gates already test current traction, so a revived old meme with live volume is a valid pool. A fit gate, not a safety one.
insider_gate_enabledtrueBlock high insider / funding-cluster %
holder_gate_enabledtrueBlock single-holder / top-10 concentration
rugcheck_veto_enabledtrueBlock high RugCheck score (the rugged-creator flag stays on regardless)
creator_rug_enabledtrueBlock creators with prior rugs
gmgn_security_enabledtrueBlock honeypot / sell-tax flags from GMGN

Thresholds:

KeyDefaultMeaning
single_holder_max_pct15Max % of supply for any single holder
top10_max_pct40Max % for top-10 holders combined
insider_cluster_max_pct10Max % held by insider/funding clusters
rugcheck_veto_normalised41RugCheck "Danger" veto line
age_min_minutes45Survive the instant-rug window
age_max_days14Meme-mode age ceiling — only applies when age_max_enabled = true
allow_token2022_extensions["metadata"]Token-2022 extensions tolerated (nothing else)

[timing] — soft, feeds the score ​

KeyDefaultMeaning
freefall_15m_max_pct-2015m return below this = penalty
ath_proximity_pct3Within this % of ATH + overextension = penalty
vol_spike_ratio3Last 5m candle ≥ 3× trailing-hour average = ignition
vol_spike_bonus0.25Score bonus for ignition

[score_caps], [smartflow], [score] ​

KeyDefaultMeaning
score_caps.bonus_cap_total10Trending + smart-flow bonuses combined never exceed this
smartflow.window_min30Rolling window (minutes) for GMGN smart-money feeds
smartflow.min_wallets / bonus_wallets3 / 4≥3 distinct smart wallets buying → +4
smartflow.min_joiners / bonus_joiners2 / 4≥2 newly-joining wallets → +4
smartflow.bonus_kol4Any KOL buy in window → +4
smartflow.net_sell_penalty_usd / penalty_net_sell5000 / 8Net smart-money selling beyond $5k → −8
score.w_fee_momentum30Score weight: fee/TVL momentum
score.w_turnover20Score weight: volume/TVL turnover
score.w_vetting_soft25Score weight: soft vetting quality
score.w_timing15Score weight: timing filter
score.w_pool_structure10Score weight: bin step / fee tier fit (weights sum to 100)

[entry] ​

KeyDefaultMeaning
fib_bottom0.786Fib retracement anchoring the range bottom
max_down_pct50Max range depth below price (was 65; deepest bins sat below where P0 fires)
min_down_pct40Minimum depth — never a thin sliver
max_quote_drift_bins3Re-quote the pool just before planning the range; skip the entry if it moved more than this many bins since the scan. 0 disables
max_position_accounts2Max DLMM position accounts per entry (69 bins each)
bin_rent_budget_sol0.075Soft rent budget (one bin array) — shrink range first
bin_rent_hard_sol0.15Hard budget (two arrays), only when score qualifies
bin_rent_hard_score_min80Score needed for the two-array budget
bin_rent_max_pos_pct25Rent is non-refundable, so it may not exceed this % of the position either. Identical to the soft budget at a 0.3 SOL entry; only binds on smaller ones. 0 = no cap
liquidity_slippage_pct5.0Active-bin slippage at open (≈5 bins at step 100; 1% caused 100% of live open failures)
tranche_enabledtrueSecond, deeper BidAsk pocket for top scores (not on young / whale-overhang entries; opens below the primary)
tranche_score_min85Score needed for a tranche
tranche_size_pct50Tranche size as % of primary
tranche_max_down_pct70Tranche target depth (clamped by the P0 safety margin to ~50%)

[manage] — the P0–P5 state machine ​

KeyDefaultMeaning
poll_s20Seconds between position polls. Every open position costs one RPC read-set per poll, so this is the main dial on RPC spend; it also sets the wall-clock length of every knob counted in polls (stop_loss_sustain_polls, rotation_polls, follow.cold_polls_end)
mark_concurrency4How many pools may be marked at once per tick. Marking used to be strictly serial, so a tick cost the sum of every position's RPC latency and mean mark gaps ran past poll_s. Same calls and same rate-limit budget — they just stop queueing behind each other. Positions in the same pool always mark one at a time; 1 restores the old serial behaviour
safety_tvl_drop_pct40P0: pool TVL drop in 10 min
tvl_drain_min_tvl_usd20000Skip tvl_drain when the pool's median TVL over the window is below this — a thin pool's TVL is a handful of LPs and swings 40–50% on ordinary repositioning (measured: same token, same 4 min, $8k pool −51% vs $67k pool −9%). pool_dead / price_crash still cover a real collapse
tvl_drain_min_pool_age_min20Skip tvl_drain on a pool younger than this — the 10-min median of a newborn pool is its own birth. Unknown age does not suppress
tvl_drain_price_rise_veto_pct25Suppress a tvl_drain exit when price rose ≥ this % over the same 10-min window — the pool is being traded through (ask-side inventory bought out), not drained. Price is the tie-breaker, not volume: a rug prints heavy volume too. 0 disables
tvl_drain_cooldown_h1Token cooldown after a tvl_drain exit (6h until v0.17.1: across 12 drain exits none was a rug and half were above the exit price an hour later). That trigger is a liquidity condition — a thin pool being traded through looks identical to a rug — so it no longer permanently bans the token and its creator. Rug-evidence triggers (pool_dead, price_crash, rugcheck_flip, holder/insider) keep the permanent one-strike ban
safety_wallet_dump_pct3P0: single holder's supply-% drop between polls
safety_new_whale_pct10P0: new wallet exceeding this % of supply
holder_poll_s90Holder-snapshot interval per open position
safety_price_crash_pct-60P0: price vs entry, at any age — deliberately no time window
stop_loss_frac0.75P1: close when SOL value < entry × this
stop_loss_sustain_polls4While below range, P1 must be under the stop for this many consecutive polls (~60s) before firing — wick tolerance. In range the stop is immediate. A violent collapse is still caught instantly by P0 price_crash
stop_loss_count_claimed_feesfalseCount fees already claimed (realized SOL in the wallet) in the value P1 compares to entry. Off = MTM only. Either way the bot logs a P1_fee_offset_deferred decision whenever the two settings would disagree, so leave it off for a week and read the Funnel before turning it on. A real crash fires identically under both
loss_reentry_cooldown_h24Cooldown after a loss exit
give_back_enabledtrueGive-back stop, meme sleeves only: once a position has been up past min(0.02 SOL, 5% of entry) fee-inclusive, close when PnL hands back to give_back_keep_frac of that peak. Exits as give_back; the token is benched 15 min like an escape. Promoted from a month of telemetry (replay +2.657 SOL / 120 closes; live triggers +0.857 SOL / 20)
give_back_keep_frac0.75Fraction of the peak PnL the position must keep; below it the give-back stop fires. Replay was flat across 0.75–0.95
rotation_fee_daily_min_pct5P2: fee-rate floor, %/day
rotation_polls3P2: consecutive polls under the floor before rotating
rotation_vol_30m_min_usd5000P2: 30m volume floor
max_age_h48P2: forced re-evaluation age
above_range_pct5P3: how far above range top counts as "above"
above_range_sustain_min10P3 wins exit after 10 min (short so follow can arm)
above_range_missed_sustain_min45P3 misses wait 45 min (10 min was churning rent)
rebalance_max_per_6h2Re-entry/rebalance rate limit
rebalance_cost_max_pct_of_fees25Skip if rent+tx would exceed this % of fees earned
reentry_ladder_mult0.75Each re-entry sizes at this × the previous
reentry_max_per_24h2Max re-entries per token per 24h
house_money_rulefalseOff: it banked notional profit with no release path
claim_min_sol0.05P4: claim when unclaimed fees reach this
claim_min_txcost_mult20…or ≥ 20× estimated tx cost
claim_interval_h4…or every 4h regardless
grace_claim_min_sol0.005Claim floor when price first drops below range (bank fees at the top of a dump)
fee_destination"bank"bank (swap fees to SOL, wallet) — compound/hybrid reserved
compound_score_min70Min pool score for compounding (if ever enabled)
escape_hatch_depth_pct60Escape hatch: dip through this % of range depth…
escape_hatch_recovery_pct25…then recovery into the top % of range → close & reset
max_position_accounts2Bin-account ceiling (69 bins each). A pool too fine-stepped to fit min_down_pct is skipped as range_too_shallow
escape_hatch_absolutetrueUse absolute drawdown from entry (arm at −26.4%, recover at −12%) instead of a fraction of range depth. On since 2026-09-05 as the range-width test's prerequisite; see RANGE-WIDTH-DECISION.md
escape_hatch_drawdown_pct26.4Absolute form: arm once price is this % below entry
escape_hatch_recovery_drawdown_pct12.0Absolute form: …then recovery to within this % of entry → close & reset
escape_reentry_cooldown_min15Bench the token this long after an escape close before re-entering it (0 = off)
profit_lock_enabledtrueBank a slice of strong runners
profit_lock_at_frac1.30Fires at mark ≥ entry × 1.30 while in range
profit_lock_withdraw_pct30Withdraw this % of liquidity
profit_lock_max_fires1At most once per position
below_range_grace_min15P5: wick-tolerance grace before closing

[sizing] — Kelly / Fixed & portfolio limits ​

KeyDefaultMeaning
mode"kelly""kelly" (ledger) or "fixed" (per-sleeve SOL / % of deployable)
max_positions5Max concurrent positions (tranches count)
min_position_sol0.3Ceiling on the position floor — the floor itself scales with your wallet (Fixed skips instead of bumping)
min_position_pct1.0Floor as a % of equity. Effective floor = max(min_position_floor_sol, min(min_position_sol, equity × this)). 0 = flat floor
min_position_floor_sol0.05Hard economic floor — below it, fees can't beat tx+rent overhead at any bankroll
min_reentry_sol0.2Separate viability floor for re-entries (reused accounts are cheaper); also capped by the scaled floor
kelly_enabledtrueMirror of mode=="kelly" (compat for older profiles)
kelly_fraction0.25Quarter-Kelly (half-Kelly assumes a proven edge)
kelly_lookback100Closed positions in the rolling estimate
kelly_min_samples25Below this, cold start applies
kelly_cold_start_frac0.03Cold start: flat 3% of wallet per position
kelly_max_position_frac0.10Hard cap: no position exceeds 10% of wallet (Kelly and Fixed)
kelly_block_negativefalseOff: negative edge clamps to the min-size floor instead of a permanent stop
kelly_core_unit / _sol / _pct / _multpct / 0.5 / 4 / 1.0Core meme base when mode=kelly. Default is a flat 4% of deployable since 2026-09-05 (SIZING-MODE-DECISION.md Gate 3: the adaptive Kelly base sat at the floor for a week after three bad closes); set kelly for the adaptive base
kelly_micro_unit / _sol / _pct / _multkelly / 0.3 / 3 / 1.0Micro sleeve when mode=kelly
kelly_majors_unit / _sol / _pct / _multsol / 0.75 / 10 / 1.0Majors when mode=kelly
kelly_follow_unit / _sol / _pct / _multsol / 0.25 / 2 / 1.0Follow legs when mode=kelly
fixed_core_unit / _sol / _pctsol / 0.5 / 5Core meme size when mode=fixed
fixed_micro_unit / _sol / _pctsol / 0.3 / 3Micro sleeve when mode=fixed
fixed_majors_unit / _sol / _pctsol / 0.75 / 10Majors when mode=fixed
fixed_follow_unit / _sol / _pctsol / 0.25 / 2Follow legs when mode=fixed
reserve_sol1.0Operational reserve, never deployed
reserve_max_pct25Caps the flat reserve_sol at this % of equity, so a small wallet still has a bankroll (no effect at or above 4 SOL)
reserve_pct10Plus this % of bankroll held back for rent/fees
per_token_max_pct40Max % of deployable in one token incl. tranche
score_mult_low / mid / high0.5 / 1.0 / 1.5Size tilt for score 60–70 / 70–85 / 85+ (Kelly only)
circuit_daily_loss_pct3Circuit breaker: realized 24h loss % of bankroll pauses new entries (open positions still managed). 0 disables the breaker
circuit_pause_h12Breaker pause length
circuit_weekly_triggers_halt2Two trips in 7 days → full halt until resumed
cluster_brake_exits4Cluster brake: this many lossy hard exits…
cluster_brake_window_h6…within this window…
cluster_brake_pause_h2…pauses new entries this long
cluster_brake_loss_pct10"Lossy" = realized ≤ −10% of entry
regime_filtertrueSOL/USD regime filter on
regime_sol_24h_halve_pct-8SOL −8%/24h → halve new sizes
regime_sol_24h_pause_pct-15SOL −15%/24h → pause new entries

[follow] — up-only re-entry chains ​

KeyDefaultMeaning
enabledtrueFollow mode on
min_vol_30m_usd100000Required to arm a chain (checked at close time) and to fire a leg — 4× the normal entry volume floor. Before v0.12.0 only firing was gated, so chains armed on quiet pools and held the token lock for hours
retrace_arm_pct15Required dip from the post-exit / post-high peak
range_depth_pct30Leg depth (tighter than the 40% default)
leg_size_sol0.25Fixed leg size — the mode earns more with its own ledger
max_legs3Per chain
chain_loss_budget_sol0.075Chain ends when cumulative leg PnL breaches this
chain_max_age_h12Chain lifetime
cold_polls_end3Consecutive polls under the normal volume floor ends the chain
open_fail_cooldown_s300Wait after a failed leg open
awaiting_dip_max_min90A chain waiting this long for its retrace ends and releases the token. Measured from when it last entered the dip-wait, not from chain start. Every leg that ever fired did so within 52 min. 0 = never

[majors] — spot parking for allowlisted alts ​

KeyDefaultMeaning
enabled / discoveryfalse / trueSleeve off by default since 2026-09-05 (43 live closes, +0.04 SOL on 837 SOL-hours); open majors positions still manage out. true re-enables; discovery sweep runs only when enabled
discovery_pages8Datapi pages for the majors sweep
symbol_allowlistPUMP, JTO, BONK, WIF, RAY, JUPOnly these symbols (ANSEM removed 2026-08-20 — it carried ~92% of majors losses on both live bots)
mcap_min_usd0No mcap floor (allowlist is the gate)
age_min_days7Token must be ≥ 7 days old
strategy_shape"spot"Uniform bins — not the meme BidAsk ramp
range_below_pct12Range depth below the active bin. The top is always the active bin — a SOL-only deposit cannot fund bins above price, so range_above_pct is ignored since v0.15.0 (kept so old configs still parse)
entry_rsi_period / entry_rsi_max14 / 45Enter when RSI ≤ 45 (oversold)…
entry_swing_position_max0.40…or price in the bottom 40% of the 24h swing
entry_swing_avoid_top0.75Never enter above 75% of the swing range
fee_tvl_24h_min_pct / fee_tvl_30m_daily_min_pct0.08 / 0.05Much lower heat floors than meme
tvl_min_usd / tvl_max_usd100000 / 10000000TVL band
vol_30m_min_usd15000Volume floor (was 5000; sub-15k entries only ever churned P2 rotations)
max_pool_share_pct5Pool-share cap
size_sol / max_position_sol0.75 / 1.5Fixed entry size / absolute cap
max_slots1One majors position at a time
deploy_cap_pct40Max % of wallet in majors
meme_reserve_slots2Majors only enter when this many slots stay free for memes
stop_loss_frac0.60Wider stop than meme (spot holds inventory)
escape_hatch_enabledfalseMajors hold through dips
below_range_grace_min1202h grace below range (vs meme 15m)
claim_min_sol0.02Claim floor
fee_compoundfalseBank only
profit_lock_enabledfalseOff for majors
max_age_h168One-week age cap
above_range_sustain_min / above_range_missed_sustain_min240 / 480Slow take-profit timers
rotation_fee_daily_min_pct0.05Rotation floor (must sit at/below the entry floor)
rotation_vol_30m_min_usd2000Rotation volume floor
rotation_polls20Sustained decay before rotating
[[majors.pools]]PUMP seedOptional whitelist seeds; discovery still finds the best live pool per symbol

[rotation] — capital agility ​

KeyDefaultMeaning
alpha_slots1Slots reserved for score ≥ alpha_score_min only
alpha_score_min85The alpha bar
displacement_enabledtrueFull book + exceptional candidate → close weakest
displacement_margin15Candidate must beat the weakest's current score by this
displacement_min_hold_min30Positions younger than this are safe
displacement_value_frac_min0.97Never displace a position > 3% underwater
displacement_max_per_6h2Displacement rate limit

[exec] ​

KeyDefaultMeaning
modepaper | liveLive also requires FARMER_MODE=live in the environment — both switches or nothing trades
exit_slippage_bps50Normal exit swap slippage
safety_exit_slippage_bps1000P0 safety exits: speed over price
tx_retries3Network retries before abandoning and re-quoting
priority_fee_percentile75Percentile of the nonzero recent fees on the accounts the tx writes. The zero-fee majority says nothing about the cost to compete
priority_fee_floor_microlamports10000Never bid below this (≈0.000002 SOL at a 200k CU limit)
priority_fee_cap_microlamports1000000Never bid above this (≈0.0002 SOL at a 200k CU limit). Raise on a congested day
priority_fee_retry_mult1.5Fee is multiplied by this per retry attempt. 1.0 disables escalation
compute_unit_margin_pct20Headroom over simulated consumption when we set the CU limit
compute_unit_fallback600000CU limit when simulation fails. Applies only to transactions we build — the DLMM SDK sets its own

Why both halves matter

A prioritization fee is price × requested compute-unit limit, and you're charged on what the transaction asks for, not what it burns. Leaving the limit unset means paying for the implicit 200k-per-instruction default — and, worse, under-reserving a multi-hop swap route so it fails on compute exhaustion. The DLMM SDK simulates and sets its own limit; for the zap swap and the small hand-built transactions the bot now simulates and sets one too.

| paper_promotion_days | 7 | Consecutive profitable paper days for live eligibility |

The 1% GNME buy-and-burn fee is hardcoded in src/executor/profitBurn.ts — not a config key. See Fees.

[watchdog] ​

KeyDefaultMeaning
rpc_blind_after_min5After this long without a successful mark: alert and freeze new entries — never liquidate blind. (The old blind close-all was removed from the code in 2026‑08, not just disabled.)

[gmgn] ​

KeyDefaultMeaning
enabledtrueAuto-off when GMGN_API_KEY is empty
intervals["5m", "1h"]Trending windows checked each scan
min_liquidity_usd10000Liquidity floor for trending entries
bonus_sustained / bonus_emerging / bonus_fading8 / 4 / 3Score bonus: trending in both windows / 5m only / 1h only
require_renouncedtrueTrending entry says mint/freeze not renounced → pre-vet skip

GMGN calls are optional enrichment. The bot serializes gmgn-cli (one in flight), paces ~1 req/s with route weights, and parks ~5 minutes on HTTP 429 (or until reset_at) — see API keys → GMGN.

[apis] ​

KeyDefault
meteora_datapihttps://dlmm.datapi.meteora.ag
rugcheckhttps://api.rugcheck.xyz
jupiter_quotehttps://lite-api.jup.ag/swap/v1
jupiter_pricehttps://lite-api.jup.ag/price/v3
jup_datapihttps://datapi.jup.ag (undocumented; soft signals only)
geckoterminalhttps://api.geckoterminal.com/api/v2 — deep candles (100 bars/call, keyless, SOL-denominated via currency=token)

[candles] ​

The Meteora datapi caps /ohlcv at 10 bars on every timeframe, which silently starved every candle reader: majors RSI(14) was never computable, the meme timing filter's "last hour" was 50 minutes, and the planner's "24h swing" was the last 10 bars. GeckoTerminal is now the primary source with the datapi as fallback — you never get fewer bars than before.

KeyDefaultMeaning
deep_source_enabledtrueUse GeckoTerminal for candles; false = datapi only (10 bars)
limit100Bars per fetch. RSI(14) needs 15+; swing/ATH checks want as many as possible
max_per_min25Rate cap (GeckoTerminal public limit is 30/min). Results are cached 60s so one fetch serves a whole tick

Environment variables (.env / data/.env) ​

Not in config.toml, but part of the same picture:

VarMeaning
FARMER_MODEpaper (default) or live — half of the live double lock
RPC_URLSolana RPC endpoint — we suggest Helius mainnet (https://mainnet.helius-rpc.com/?api-key=…)
JUPITER_API_KEYJupiter Developer Portal API key for exit swaps (free tier OK)
GMGN_API_KEYOptional — GMGN query key for trending/vetting enrichment. See API keys
WALLET_PRIVATE_KEY / WALLET_KEYPAIR_PATHLive wallet (or use the dashboard's encrypted wallet instead)
WALLET_PASSPHRASEOptional (Railway): auto-unlock the encrypted wallet on boot
DASH_TOKEN / DASH_PORTDashboard auth token and port (default 8787)
FARMER_CONFIG_PATH / FARMER_ENV_PATH / FARMER_DB_PATHOverride runtime file locations (PM2 ecosystem sets these under data/)

StrategyRisk & sizingProfilesconfig.toml