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)
copycat_ignore_h24Losers of symbol dedupe ignored this long (hours)

[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
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
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 via RugCheck, not pool age)
age_max_enabledtrueBlock "too old"
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
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_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
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
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_s15Seconds between position polls
safety_tvl_drop_pct40P0: pool TVL drop in 10 min
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
loss_reentry_cooldown_h24Cooldown after a loss exit
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
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.3Floor — below it, fees can't beat tx+rent overhead (Fixed skips instead of bumping)
min_reentry_sol0.2Separate viability floor for re-entries (reused accounts are cheaper)
kelly_enabledtrueMirror of mode=="kelly" (compat for older profiles)
kelly_fraction0.25Quarter-Kelly (half-Kelly assumes a proven edge)
kelly_lookback50Closed positions in the rolling estimate
kelly_min_samples50Below 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 / _multkelly / 0.5 / 5 / 1.0Core meme base when mode=kelly
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_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
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_usd100000Arm only at 4× the normal entry volume floor
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

[majors] — spot parking for allowlisted alts

KeyDefaultMeaning
enabled / discoverytrue / trueSleeve on; discovery sweep on
discovery_pages8Datapi pages for the majors sweep
symbol_allowlistPUMP, ANSEM, JTO, BONK, WIF, RAY, JUPOnly these symbols
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_pct / range_above_pct12 / 6Band below/above price — SOL biased to the downside
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_usd5000Volume floor
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, ANSEM seedsOptional 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
use_zaptrueMeteora Zap SDK (Jupiter V6) for token→SOL; lite-Jupiter fallback on failure
exit_slippage_bps50Normal exit swap slippage
safety_exit_slippage_bps1000P0 safety exits: speed over price
tx_retries3Network retries before abandoning and re-quoting
paper_promotion_days7Consecutive 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)

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