# MAXBOT — Full Context Prompt Paste this at the start of any new conversation to restore full context. --- ## Instructions for Claude When you read this file, you are fully caught up on the bot's logic, strategy, and current state. Do not ask questions already answered here. **IMPORTANT — keep this file current:** At the end of any conversation where a major change, new feature, or significant decision was made, update this CONTEXT.md to reflect it. Provide the updated file for George to commit alongside the code changes. A good rule of thumb: if it would be confusing to a future Claude reading this cold, update it. --- ## Git repository - Gitea: `http://minimax.lan:3000/george/maxbot.git` - Server: `~/maxbot` on `portainer.local` (user: george) - Branch: `main` **Workflow for every change:** ```bash # On Ubuntu server after updating files cd ~/maxbot git add -A git commit -m "Short description of what changed" git push ``` **To pull latest on server:** ```bash cd ~/maxbot && git pull sudo systemctl restart maxbot ``` **To see history:** ```bash git log --oneline ``` **To revert a bad change:** ```bash git revert HEAD # undo last commit sudo systemctl restart maxbot ``` --- ## What this is A live grid trading bot running on Ubuntu server (portainer.local), trading TSLA CFDs on Capital.com. Written in Python, running as a systemd service. Account owner: George, UK retail account, GBP, 5:1 leverage (20% margin). --- ## Project structure ``` ~/maxbot/ bot.py — main entry point, loop, startup audit, CLI config.py — ALL settings (edit this for day-to-day changes) client.py — Capital.com REST API calls state.py — account state snapshot, field access helpers calculator.py — grid maths, survival check, tier lookups grid.py — order management logic (gap-filling, TP rules, dip mode) actions.py — dry/confirm/live action handler with visible logging calibration.py — startup calibration report, history sync fetch_history.py — fetches full Capital.com transaction history to SQLite data/history.db — SQLite: all trades, swaps, deposits from Jan 2021 logs/ bot.log — full detail every loop actions.log — actions only (orders placed/cancelled/TP changes) calibration.log — startup calibration reports fetch_history.log ``` --- ## The trading strategy **Instrument:** TSLA CFD on Capital.com (UK retail, GBP account) **Type:** Grid / mean-reversion dip buying 1. Bot places limit buy orders BELOW current price at regular intervals 2. When TSLA dips, orders fill automatically 3. Each position has a take profit set to return exactly £1.00 (0.2 shares) or £0.50 (0.1 shares) 4. Take profit is set as an ABSOLUTE PRICE LEVEL (not amount/distance) Formula: tp_pct = (profit_gbp * gbpusd / size) / entry_price tp_price = entry_price * (1 + tp_pct) 5. Positions close automatically at take profit 6. Strategy works as long as TSLA doesn't drop catastrophically and long-term price grows **Position sizes:** - 0.2 shares: below SIZE_SMALL_THRESHOLD (highest_open * 0.95) - 0.1 shares: within top 5% of highest open price (expensive overnight) **Profit targets (configurable in config.py):** - TP_PROFIT_LARGE = 1.00 (£1.00 for 0.2 share positions) - TP_PROFIT_SMALL = 0.50 (£0.50 for 0.1 share positions) --- ## Grid logic **Anchor:** Grid starts just below the LOWEST OPEN POSITION (not current price). This prevents churn from minute-to-minute price movements. Grid only shifts when a position actually fills. **Normal mode** (price within 25% of highest open): - Anchor = lowest open position - Grid fills below anchor, queue_depth orders maintained **Dip mode** (price dropped 25%+ from highest open): - Lowest open position has TP DISABLED (manual close only) - Anchor = second lowest open position (lowest with TP) - Grid fills below anchor - Also fills gaps between no-TP position and anchor if spacing fits - No orders placed at or above anchor or no-TP position **Grid floor:** Always fixed at 60% drop from highest open position. Floor = highest_open * 0.40. Never changes regardless of other settings. **Queue depth:** Always maintain exactly QUEUE_DEPTH pending orders in the grid window. Scan for gaps anywhere (not just bottom) and fill them. Cancel orders outside the window. --- ## Bottom-two position rule Only activates when price drops 25%+ from highest open: - Lowest open position → TP DISABLED (manual close, holds for max recovery) - Second lowest → TP ENABLED at standard level - When new lower position opens → re-evaluate bottom two --- ## Survival system (CRITICAL — everything depends on this) **The survival check simulates a FULL 60% drop from highest open position.** It does NOT just check current orders. It simulates: 1. All existing open positions 2. ALL grid levels from lowest existing down to floor (no depth cap) — because in a real crash, every level fills on the way down Formula: - Floor = highest_open * 0.40 - For each level: margin = price * size * 0.20 / gbpusd - For each level: unrealised_loss = (floor - price) * size / gbpusd - equity_at_floor = current_equity + sum(unrealised_losses) - margin_level_at_floor = equity_at_floor / total_margin * 100 - SAFE if margin_level_at_floor >= 50% (Capital.com closeout threshold) **Capital.com margin stages:** - >100%: normal - ≤100%: warning 1 — bot stops placing orders - ≤75%: warning 2 — urgent - ≤50%: auto closeout — Capital.com closes positions **SURVIVAL_DROP_PCT in config.py:** This is the bot's operational setting. It auto-steps (30→35→40→45→50→55→60%) as equity grows. It does NOT control grid depth — the grid always goes to 60% floor regardless. SURVIVAL_DROP_PCT is used to gate order placement in the main loop. **Auto-update:** Calibration checks max safe % each startup. If account can survive a higher milestone, config.py is auto-updated. --- ## Grid tier upgrades (survival-gated) **ORDER OF OPERATIONS — strictly enforced:** 1. Survival check first (always, against full 60% simulation) 2. Spacing tightens second (only when 60% survival passes at tighter spacing) 3. Depth increases third (only after spacing tightened AND 60% survival passes) Spacing tiers (config.py SPACING_TIERS): - £600: 1.5% (base) - £800: 1.2% (only if 60% survival passes at 1.2%) - £1100: 1.0% - £1500: 0.8% Queue depth tiers (config.py QUEUE_TIERS): - (£600, 10 orders, requires 1.5% spacing) - (£900, 12 orders, requires 1.2% spacing first) - (£1200, 15 orders, requires 1.0% spacing first) - (£1500, 18 orders, requires 0.8% spacing first) Depth NEVER increases until spacing has already tightened to required level. Spacing NEVER tightens until full 60% drop simulation passes. --- ## Calibration report (runs every startup) Sections in logic order: 1. ACCOUNT — equity, margin, positions, deposits 2. SURVIVAL — max safe %, progress to 60%, auto-update status 3. GRID — current spacing/depth, next upgrade status (survival-gated) 4. TSLA PERFORMANCE — trades, profit, fees, monthly trend (from Jan 2024) 5. MILESTONES — £1k, £10k, £100k, £1M with ETA based on real profit rate Deposit detection: auto-detects weekly average from Capital.com history (last 12 weeks, needs 3+ deposits). Falls back to WEEKLY_DEPOSIT_GBP in config.py. History sync: fetch_history.py runs incrementally on every startup, fetching only new days since last run. Uses /history/transactions endpoint. 3 second delay to avoid Capital.com session rate limit (429). --- ## Operating modes ``` python3 bot.py --mode dryrun # reads everything, prints what it would do, no actions python3 bot.py --mode confirm # asks y/n before every action python3 bot.py --mode live # fully autonomous ``` Service: systemd, auto-restart, credentials in ~/maxbot/.env --- ## Capital.com API notes - Field names (verified against live API): Orders: workingOrderData.orderLevel, orderSize, dealId Positions: position.level, position.size, position.profitLevel, position.dealId Account: accounts[].balance.balance (equity), .deposit (funds), .available Price: snapshot.bid, snapshot.offer - Session tokens expire after 10 minutes, refresh at 9 minutes - Rate limit: 1 request per 0.1s for order operations - POST /session: 1 request/second limit - TP is sent as profitLevel (absolute price), displays as "Price level" in UI - No custom order tags/references available in API --- ## Current state (as of May 27 2026) - Equity: ~£664 - Highest open position: $450.02 - Max safe survival: 40% drop - SURVIVAL_DROP_PCT: 40% - Grid: 1.5% spacing, 10 orders, FROZEN until 60% survival met - Account open: Jan 28 2021 - Current strategy start: Jan 2024 - Trades (Jan 2024+): 407, profit £484, fees -£74, net £409 - Blended daily rate: £2.67/day - Next milestone: £1,000 equity (~126 days at current rate) - Weekly deposits: none detected yet (last deposit May 26 2026) --- ## Planned future features (not yet built) 1. Telegram alerts — fills, closures, margin warnings 2. Auto survival threshold stepping already done 3. Claude AI integration — consult Claude on edge cases 4. Web dashboard — browser view of positions, grid, P&L 5. ProQuant-style backtester — test strategies against TSLA history (data already in history.db, S&P500/NASDAQ planned as context) 6. US100 and S&P500 as secondary instruments (future) --- ## Key design decisions made - Grid floor FIXED at 60% — never changes, decoupled from SURVIVAL_DROP_PCT - TP as price level % of entry (not fixed dollar, not fixed % of current price) - Grid anchored to lowest OPEN POSITION (not current price) — prevents churn - Survival always simulates FULL grid to floor (no depth cap) — honest - Spacing frozen until 60% survival passes — safety before profit frequency - Depth requires spacing first — correct order of operations - History uses /history/transactions not /history/activity (richer data) - Deposits filtered from Jan 1 2024 onwards (new strategy era) - SURVIVAL_DROP_PCT auto-steps in config.py via calibration — no manual edits