Replace skeletal wizard (window title only) with complete click-to-sample flow: - Screenshot target window via mss+pygetwindow (Windows) or --screenshot PNG - Single-canvas Tk wizard with scaled display + back/skip/save controls - Stepwise clicks collect: dot_roi, all 7 dot colours (+ optional background), chart_roi, 2 y-axis reference points with prices, canary region - Auto-compute canary baseline phash at save time - Pull Discord/Telegram creds from ATM_DISCORD_URL/ATM_TG_TOKEN/ATM_TG_CHAT env - Add --screenshot flag to 'atm calibrate' for non-Windows dev testing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ATM — Automated Trading Monitor
Personal tool for the M2D strategy on TradeStation DIA/GLD charts with US30/XAUUSD execution on TradeLocker. The bot watches the colored dot strip produced by the M2D MAPS custom indicator and sends a Telegram/Discord notification (with chart screenshot + SL/TP levels) when a BUY or SELL trigger fires — so you execute the trade manually in TradeLocker instead of watching two screens.
Current phase: Faza 1 — notification-only. No auto-execution until prop firm TOS has been audited (see docs/phase2-prop-firm-audit.md).
Project structure
atm/
├── pyproject.toml
├── configs/ # calibration configs (YYYY-MM-DD-HHMM.toml + current.txt)
├── logs/ # audit JSONL + dead-letter queue
├── samples/ # screenshots for dry-run validation
└── src/atm/
├── config.py # Config dataclass + loader
├── detector.py # screenshot → color → state machine
├── state_machine.py
├── vision.py # color matching helpers
├── levels.py # SL/TP pixel-to-price
├── calibrate.py # Tkinter calibration wizard
├── labeler.py # Tkinter sample labeler
├── journal.py # trade journal (JSONL)
├── report.py # weekly performance report
├── audit.py # structured audit log
├── canary.py # layout drift detection
├── dryrun.py # replay saved screenshots
├── notifier/
│ ├── discord.py
│ └── telegram.py
└── main.py # unified CLI
Setup
Prerequisites
- Python 3.11+
- Windows 10/11 (required for live capture; dry-run works on any OS)
- TradeStation running with a 3-minute DIA or GLD chart open
Install
# Clone (internal repo)
git clone git@gitea.romfast.ro:romfast/atm.git
cd atm
# Create venv and install
python -m venv .venv
.venv\Scripts\activate # Windows
pip install -e .
# Windows-only extras (screen capture, window detection)
pip install -e ".[windows]"
Environment variables (notifiers)
Create a .env file or set these in your shell before running:
ATM_DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
ATM_TELEGRAM_TOKEN=123456789:AABBcc...
ATM_TELEGRAM_CHAT_ID=-100123456789
Calibration workflow
Calibration maps the TradeStation window layout to the config that drives detection. Redo calibration whenever you resize the chart window, change DPI, or switch monitors.
Step-by-step
-
Open TradeStation with the 3-minute DIA chart. Maximise or snap to a fixed position. Do not resize it during the session.
-
Run the calibration wizard:
atm calibrate -
Pick window title — type the exact string that appears in the TradeStation title bar (e.g.
DIA - 3 Min). The bot uses this to locate the window viapygetwindow. -
Mark the dot ROI — a screenshot of the current window is shown. Click the top-left corner and the bottom-right corner of the M2D MAPS dot strip to define the region of interest.
-
Sample dot colours — for each of the 7 dot colours (turquoise, yellow, dark green, dark red, light green, light red, gray), click a representative dot in the screenshot. The wizard records the RGB value and sets an initial tolerance of 30.
-
Set y-axis calibration points — click on two price levels that appear as visible horizontal gridlines on the chart, then type the corresponding price for each. This calibrates the pixel-y → price mapping for SL/TP extraction.
-
Select canary region — drag a small rectangle over a stable, unchanging part of the chart border (title bar strip works well). This becomes the baseline for canary drift detection.
-
Save — the wizard writes
configs/YYYY-MM-DD-HHMM.tomland updatesconfigs/current.txt. Future runs load this config automatically.
Verify calibration
atm dryrun --dir samples/
Review the dry-run output. Every sample should classify to the expected dot colour. If misclassifications appear, re-run the calibration wizard or adjust tolerances manually in the TOML file.
Per-session operating checklist
Before each trading window (NY open 16:30 RO, NY close 21:00 RO):
- TradeStation open on 3-minute DIA chart, window not minimised
- Chart window is in the same position/size as when calibrated
- TradeLocker open in browser, instrument US30 loaded, position sizing ready
- Telegram / Discord notification channel visible on mobile or second screen
- Run
atm canary-check— confirm no drift alert before starting the bot - Start the monitor:
atm run - After the session:
atm journal addto record trade outcome (or leaveoutcome=opento fill later) - At week end:
atm report --week YYYY-WWto review win rate and PnL in R
DPI and multi-monitor notes
-
High-DPI displays: Windows DPI scaling can shift pixel coordinates. Set TradeStation to "System (Enhanced)" DPI compatibility mode (right-click EXE → Properties → Compatibility → Change high DPI settings) OR set Python to DPI-unaware via
SetProcessDPIAware()in the manifest. The calibration wizard and capture code both callSetProcessDPIAware()on start. -
Multiple monitors:
msscaptures the monitor that contains the target window. The ROI offsets in the config are relative to the window's own top-left, so moving the window between sessions (but not resizing) is usually safe. Moving to a different monitor with a different DPI requires recalibration. -
Virtual desktops / remote desktop: Screen capture via
mssdoes not work through RDP (the window reports on-screen but the pixel data is black). Run the bot locally on the same physical machine as TradeStation.
Troubleshooting
Window not found
WindowNotFoundError: No window matching 'DIA - 3 Min'
Causes and fixes:
- TradeStation is minimised — restore it to a visible state.
- The window title has changed — re-run
atm calibrateand provide the exact current title string. Copy-paste from the title bar. - DPI scaling changed the reported title encoding — confirm the title in
pygetwindow.getWindowsWithTitle("")output.
Canary drift alert
CanaryDriftAlert: phash distance 12 > threshold 8
The chart layout has shifted (e.g., chart scroll, zoom change, indicator redraw). Do not trade until this is resolved.
- Check TradeStation — scroll or zoom may have shifted the DOT ROI out of frame.
- Reset the chart to the calibrated state (same zoom/scroll as during calibration).
- If the layout change was intentional, re-run calibration.
- To suppress a single false alarm without recalibrating, run
atm canary-resetwhich re-samples the canary region baseline from the current screenshot.
Low confidence warnings
LowConfidence: cycle 5 — best match 'gray' dist=0.27 (threshold 0.20)
The sampled pixel is near the edge of a colour tolerance zone. Usually caused by:
- Screenshot timing during a dot colour transition (rare on 3-min chart).
- Chart re-render artifact (scaling seam at ROI boundary).
If this persists for more than 3 consecutive cycles, an alert is sent automatically. Verify the dot strip is fully visible and not clipped by another window.
Notification not received
- Check
logs/audit.jsonlfor the last cycle — look for"notification_sent": falseand thereasonfield. - Verify webhook/token:
atm test-notify. - Check network connectivity from the Windows machine to Discord/Telegram endpoints.