2be8b491d0
- Grid strategy with survival-gated spacing and depth - Full 60% drop simulation for all survival checks - Calibration report with auto-updating survival threshold - Transaction history sync from Capital.com - Dip mode with bottom-two TP rules
241 lines
8.9 KiB
Markdown
241 lines
8.9 KiB
Markdown
# MAXBOT — Full Context Prompt
|
|
|
|
Paste this at the start of any new conversation to restore full context.
|
|
|
|
---
|
|
|
|
## 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
|