Files
maxbot/CONTEXT.md
T
2026-05-27 07:04:49 +01:00

9.4 KiB

MAXBOT — Full Context Prompt

Paste this at the start of any new conversation to restore full context.


Git repository

  • Gitea: http://minimax.lan:3000/george/maxbot.git
  • Server: ~/maxbot on portainer.local (user: george)
  • Branch: main

Workflow for every change:

# 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:

cd ~/maxbot && git pull
sudo systemctl restart maxbot

To see history:

git log --oneline

To revert a bad change:

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