π Toss Auto-Trading Dev Journal (Phase 7 Β· 19 posts so far)
- Phase 0 – Project Foundation
- Phase 0-1 – Currency Bug Fix
- Phase 1 – Config Separation & Retry Logic
- Phase 1-2 – Config/Retry Follow-up
- Phase 1-3 – Introducing pytest
- Phase 1-4 – Log Rotation
- Phase 2-1 – Strategy Class Design
- Phase 2-2 – Multi-Symbol Monitoring
- Phase 3-1 – Data Persistence Design
- Phase 3-2 – DB Module Implementation
- Phase 3-3 – DB Integration
- Phase 2-3 – Strategy Plugin Interface
- Phase 4 – Backtest Engine
- Phase 4 – Candle API Pagination
- Phase 5 – Read-Only Dashboard
- Phase 5 – Telegram Control Logic
- Phase 5 – Telegram Control Logic 2
- Phase 6 – Scheduler/Watchdog
- Phase 7 – Order Quantity Guardrail (this post)
This post: Phase 7 / #19
π νκ΅μ΄λ‘ 보기
π‘ Phase 7 Summary
- Goal: Add a guardrail preventing unintentionally large order sizes caused by bugs or config mistakes
- Key decision: Inserted as a “layer 0” check that runs before DRY_RUN, so even simulation mode catches oversized orders
- Verification: 4 new tests added, full pytest suite passes at 122/122 (118 existing + 4 new)
From Phase 0 to Phase 7: Getting Ready to Go Live
Phases 0 through 6 built up the bot piece by piece β config separation, a strategy class, database persistence, a backtest engine, Telegram control, a scheduler with a watchdog. The last item on the roadmap is Phase 7: getting ready for live trading, starting with a new order quantity guardrail.
That name alone makes this phase feel heavier than the rest. Everything so far has run safely inside DRY_RUN mode, but once Phase 7 wraps up, real orders could eventually hit a real account. So instead of flipping the safety switches off right away, I decided to work through a short checklist of things worth preparing first.
The pre-live checklist
- Order quantity guardrail (today’s topic)
- Daily/cumulative loss limit with auto-pause
- Backtest verification with real target prices and strategy
- (after explicit approval) Gradual removal of the three-layer safety net
Given usage limits, I’m tackling one item per day. Today: the order quantity guardrail.
The Problem: Nothing Stopped an Oversized Order
Going back through the code, one gap stood out. A bug in quantity calculation, or a config typo, could send an unintentionally large order to the market. The existing three-layer safety net (DRY_RUN, a 1-won target price, and physically commented-out order API calls) blocks trades themselves, but it doesn’t catch a logic mistake in the code.
So I added a new setting, MAX_ORDER_QUANTITY_PER_TRADE, to config.py, defaulting to 10 shares. Any single order exceeding that gets rejected outright β this is the order quantity guardrail at the center of today’s post.
Design: Checking This Before DRY_RUN
The key design decision here was where in the pipeline this order quantity guardrail runs. I inserted it as a “layer 0” check that fires before the existing three-layer safety net, inside execute_order().
Why does the ordering matter? Because if the guardrail rejects an oversized order even while DRY_RUN=True, I can catch quantity-calculation bugs during simulation β well before anything goes live, instead of discovering them right before flipping the safety switches off.
Using a masked example (Samsung Electronics, ticker 005930): an order meant to buy 5 shares that accidentally becomes 500 shares due to a calculation bug gets caught right here, at layer 0.
Note: an order that exceeds the limit only triggers an ERROR-level alert β it’s never written into the trade history. That keeps trades that never actually executed from contaminating P&L statistics later on.
Verification: 4 New Tests, 122/122 Passing
I added three tests to test_auto_trader.py:
- An oversized order gets rejected
- An order exactly at the limit (e.g. 10 shares) still executes normally
- A rejected order never appears in the trade history
I also added a regression test to test_config.py confirming the limit itself stays within a sane range (1β100). If that value ever gets accidentally bumped way too high, the whole guardrail becomes meaningless β this test exists to catch that mistake before it happens.
Running the full pytest suite afterward confirmed all 122 tests passing (118 existing + 4 new), and I double-checked that the existing DRY_RUN and TARGET_BUY_PRICE safety values were untouched.
The order quantity guardrail is designed as a “layer 0” check running before DRY_RUN, so even simulation mode catches quantity-calculation bugs before going live.
Result: A Four-Layer Safety Net
| Layer | What it does |
|---|---|
| 0 (new) | Rejects any order exceeding the quantity limit |
| 1 | DRY_RUN=True simulation mode |
| 2 | Target price set to 1 won (unfillable) |
| 3 | Order API physically commented out |
Both the local environment and the project repo are synced and confirmed.
What’s Next: Auto-Pause on Loss Limits
Next up is a guardrail that auto-pauses the monitoring loop once daily or cumulative losses cross a threshold, reusing the engine_control.pause() method built back in Phase 5. After that comes backtest verification with real target prices and strategy, and finally β once explicitly approved β the gradual removal of the three-layer safety net.
FAQ
Q1. Why does the order quantity guardrail run before DRY_RUN?
Rejecting oversized orders even in simulation mode means quantity-calculation bugs get caught before going live, not discovered right before the safety switches come off.
Q2. Does a rejected order show up in trade history?
No β it only triggers an ERROR-level alert and is never written to the trade history, so failed simulated trades don’t skew P&L statistics.
Q3. What’s the default order limit?
MAX_ORDER_QUANTITY_PER_TRADE defaults to 10 shares and is configurable.
Q4. What’s the next Phase about?
An auto-pause guardrail that halts the monitoring loop once daily or cumulative losses exceed a set threshold.
Pingback: 1ν μ£Όλ¬Έ νλ λ°©μ΄ λ‘μ§μΌλ‘ μμ μ₯μΉ κ°ννκΈ° | ν μ€ μλλ§€λ§€ κ°λ°κΈ° #19 - TS ννΈ: μ£Όμ μλλ§€λ§€ μ°κ΅¬μ
Pingback: Auto-Pausing on Cumulative Loss Limit | Toss Auto-Trading Dev Journal #20 - Orbit - Space & ETF Investing
Pingback: Toss Auto-Trading Bot: Take-Profit/Stop-Loss Cycle Complete #23 - Orbit - Space & ETF Investing
Pingback: Trading Bot Dashboard with FastAPI | Toss Dev Journal #24 - Orbit - Space & ETF Investing
Pingback: Toss Securities Holdings Dashboard | Dev Journal #25 - Orbit - Space & ETF Investing