feat / add adaptive grid trader agent - #179
Open
rapcmia wants to merge 6 commits into
Open
Conversation
rapcmia
marked this pull request as draft
July 28, 2026 15:43
Reworks the adaptive grid trader around a two-layer decision system: baseline_7d decides the first grid, hourly_mtf_check (1h/4h/1d) manages the running one behind an anti-flip rule. - add skills/liquidation_guard: pre-deploy gate covering order sizing, worst-case fill position, and liquidation-vs-limit_price check - drop routines/order_size_validator; sizing is now step 0 of the gate - add btc_usdt_adaptive_grid and sol_usdt_adaptive_grid strategies with fixed risk envelopes and per-tick procedures - rewrite both routines for ATR-derived ranges and EMA trend detection Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rapcmia
marked this pull request as ready for review
July 30, 2026 16:21
A grid_executor has no position_mode field and never sets one, so it inherits whatever the account has. On a ONEWAY account a second grid nets against the first instead of holding independently, which makes the level math and the liquidation guard compute a position that does not exist. - add routines/position_mode_check: read-only capability probe that resolves to HEDGE or ONEWAY and reports two_sided_allowed. Unreadable or unrecognised responses default to ONEWAY (fail-closed) - gate the NEUTRAL ladder's TWO_SIDED rung on two_sided_allowed - keep first entry baseline-driven; the hourly check can no longer veto it - note in setup that the user sets position mode, not the agent Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
_trend_direction bails out below slow + 2 = 23 candles, but the routine fetched only 20 daily candles. The daily timeframe therefore returned NEUTRAL unconditionally — proven with a synthetic 2%-per-candle uptrend, which reads NEUTRAL at 20 candles and BULLISH at 23. Because a direction change requires both 4h and 1d to agree, flips were unreachable: cases E and F never fired, case B always fell through to the baseline, and confidence could never exceed LOW. - fetch 60 candles for both 4h and 1d, with the 23-candle floor documented - drop stale "proxy for 6h / 12h" comments left from the previous design - add triple_barrier stop_loss (0.10) so a losing grid closes on PnL instead of waiting for limit_price or the time limit; note that it measures filled-position PnL, not budget Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The baseline sat on NEUTRAL through obvious moves because it only looked at EMA separation, and a running grid had no feedback path at all — it was kept or flipped purely on chart agreement. baseline_7d: - EMA separation threshold 0.3 -> 0.15 ATR - add a price-action override: price on one side of both EMAs with a 48h slope past +/-1% reads directional even while EMAs are still crossing - add a soft nudge at +/-0.25% for the remaining NEUTRAL cases - retune strength bands to 0.15 / 0.8, and report price-vs-EMAs and slope Layer 2, checked before keep/flip in priority order: - stale grids that stopped filling are torn down and rebuilt on a fresh range - grids at >=2% unrealized profit of trade budget are banked - sustained worsening PnL counts as a confirming vote, substituting for one missing timeframe; it never overrides a clear opposite baseline Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Verified working with Note: |
- set leverage in the executor payload; omitted, it falls back to a default well above the envelope cap - leverage comes from the envelope, not agent discretion; ask the user once at session start - stale detection no longer requires a grid older than its time_limit, which the executor never allows to exist Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the Adaptive Grid Trader — an agent that runs a grid bot and re-decides, once an hour, which way that grid should lean.
A grid bot places a ladder of buy and sell orders across a price range and profits from price bouncing between them. The hard part is that a ladder built for yesterday's market is wrong today. This agent handles that: it reads the market, builds a grid whose range comes from measured volatility, then checks every hour whether that grid still makes sense.
Safety, before anything deploys: the range comes from ATR, never a hardcoded percentage.
limit_priceis the single exit and sits outside normal noise, so worst-case loss is a number you know before deploying rather than discover on trigger. Leverage is checked so the exchange's liquidation price can't fire ahead of your own exit. A stop loss closes a grid that's losing, and atime_limitacts as a dead-man's switch so an unsupervised grid closes itself. Two grids never open unless the account is confirmed to support it. If no grid can be built safely, the answer is HOLD — the agent never raises the budget to make one fit.Before you run it
Close anything open on the connector, then ask any Condor agent with trading tools to set your position mode — the grid agent won't do it itself:
What's in it
The decision cases
Every tick lands in exactly one case. This is the whole control loop — there's no other path to a deploy or a teardown.
Before it flips, two things must be true: both the 4-hour and daily charts agree on the new direction, and the grid has been open at least 3 hours. Together they stop it from flip-flopping. Most hours land on C or D — nothing to do.
Three checks run before that keep/flip decision, in this order:
A clear 7-day trend still wins. Losses can break a tie, but they can't override the trend.
The NEUTRAL ladder (Case A with no baseline direction) — try in order, stop at the first rung that passes the capability gate, sizing, and the liquidation guard:
two_sided_allowed: YES, TWO_SIDED in the strategy envelope, ≥2 executor slots, and each leg viable on half the budget.Two rules that shape everything
The hourly check can never veto a first entry. With no grid running, direction comes from the baseline alone and hourly only supplies range prices. If hourly returns
HOLDorNOT ACTIONABLE, the agent still deploys and computes the prices itself from ATR. Hourly holds authority only over a grid that already exists — because range-bound markets are exactly what make hourly say HOLD, and those are a grid bot's best conditions.Two grids require proof, not assumption. A
grid_executorhas noposition_modefield and never sets one, so it silently inherits whatever the account has. On a one-way account, a second grid nets against the first instead of holding independently — the level math and the liquidation guard would both be computing a position that doesn't exist. So TWO_SIDED is gated on a live read, and anything unreadable is treated as one-way.Routines — the deterministic math
Routines are plain Python that fetch data and compute numbers, so the same input always gives the same answer.
baseline_7dhourly_mtf_checkstart_price,end_price,limit_priceplus the manage-the-running-grid signalposition_mode_checktwo_sided_allowed: YES/NOposition_mode_checkalways resolves toHEDGEorONEWAY— an unreadable or unrecognised response defaults toONEWAYand says so on amode_read:line. It's read-only: it never changes the mode, never places orders. Condor's MCP layer exposes only a setter for position mode, so the routine reads it straight from HAPI through the client routines already hold.Skill — the gate before deployment
skills/liquidation_guard/SKILL.mdruns after prices are known and before any executor is created. It stops on the first failure:limit_price, so your exit fires first.Strategies — two samples to start from
Each strategy is one market with a fixed budget and risk envelope. Both are small on purpose, so you can watch a real grid run without much at risk.
btc_usdt_adaptive_grid— BTC-USDT on Bitget, 60 USDT. One-sided only.sol_usdt_adaptive_grid— SOL-USDT on Binance, 100 USDT. Can go two-sided when the account allows it.Copy either one, change the pair and budget, and you have a new strategy. The two differ mainly in budget, which is what decides whether two-sided grids fit at all.
Validation
ruff check agents/adaptive_grid_trader— all checks passedpython -m compileall -q agents/adaptive_grid_trader— cleanposition_mode_checkexercised against a mock client across 15 cases: both real modes, five response-shape variants, zero-size positions, and both failure paths. Every unreadable or failing case resolves toONEWAY/two_sided_allowed: NO.