Abstracting Strategy Classes for Cleaner Trading Logic | Toss Dev #2-1

Quick context if you’re new here: this is a personal Python trading bot built on the API for Toss Securities, a Korean brokerage. After wrapping up Phase 1 (config centralization, a retry decorator, pytest coverage, log rotation), the roadmap’s next item was strategy modularization.

Up to this point, the buy condition โ€” “buy if current price โ‰ค target price” โ€” was just an if statement hardcoded inside the monitoring loop in auto_trader.py. Fine for one rule, but adding a second condition (a moving average, RSI, whatever) later would mean touching that loop again every time.

Why bother now

I don’t have an immediate plan to add a moving-average strategy, but the structural debt bothered me โ€” needing to open the loop code every time a new rule shows up isn’t sustainable. So I split Phase 2 into three steps:

  • โ‘  Abstract the existing condition into a class
  • โ‘ก Design a plugin-style strategy interface
  • โ‘ข Support monitoring multiple symbols instead of one

Doing all three at once seemed like a good way to make verification messy, so this session was scoped to just step โ‘ . The safety net (DRY_RUN, TARGET_BUY_PRICE) stayed completely untouched.

New strategy.py โ€” the ThresholdBuyStrategy class

I created a new file, strategy.py, with a ThresholdBuyStrategy class, and moved the existing condition into a should_buy(current_price) method. Nothing about the value or the logic changed โ€” just how it’s expressed, which kept the risk low.

class ThresholdBuyStrategy:
    def __init__(self, target_price: float):
        self.target_price = target_price

    def should_buy(self, current_price: float) -> bool:
        return current_price <= self.target_price

(Sample code โ€” the actual ticker and target price are masked with a placeholder like Samsung Electronics, 005930, and an arbitrary amount.)

The hardcoded if current_price <= TARGET_BUY_PRICE: inside the loop in auto_trader.py became a single call: if buy_strategy.should_buy(current_price):. The target price is still injected from TARGET_BUY_PRICE in config.py, unchanged.

Verification โ€” 38 passing tests

I added test_strategy.py with four new tests: the normal case, the boundary case (current price exactly equal to target), and a scenario using the real safety-net value (a 1-won target). Running the full suite again: 34 existing + 4 new = 38 passing tests.

I didn’t stop at tests passing โ€” I also ran python auto_trader.py briefly to confirm it still polled every 5 seconds as before, correctly generated no buy signal (since the target is set to 1 won), and shut down cleanly on Ctrl+C.

A side note โ€” project storage overwrite behavior

While syncing the modified files into project storage, I wanted to know whether re-uploading a file with the same name would automatically overwrite the old one. It doesn’t โ€” project attachments on this platform are read-only, so re-uploading under the same name can create a duplicate instead of overwriting. I switched to deleting the old file first, then re-uploading.

What’s next

Two items remain in Phase 2. Next up is multi-symbol monitoring support, followed by designing a plugin interface for indicator-based strategies like moving averages or RSI.

FAQ

Does moving the logic into a class hurt performance?

No โ€” it’s one extra method call, negligible against a 5-second polling loop.

Did the safety net change?

No. This was purely a refactor of how the logic is expressed; the values and behavior are untouched.

Why not design the plugin interface in the same session?

Designing the interface upfront would have expanded the scope needing verification. Keeping this session to just the class abstraction kept the risk contained.

4 thoughts on “Abstracting Strategy Classes for Cleaner Trading Logic | Toss Dev #2-1”

  1. Pingback: [Toss Auto-Trading Dev Journal #9] Why I Locked Down the Data Persistence Design Before Writing a Single Line - Orbit - Space & ETF Investing

  2. Pingback: [Toss Auto-Trading Dev Journal #10] Building the SQLite Persistence Module - Orbit - Space & ETF Investing

  3. Pingback: Plugin Interface for Trading Strategies | Toss Auto-Trading Dev Journal #12 (Phase 2-3) - Orbit - Space & ETF Investing

  4. Pingback: Wiring Up python-telegram-bot Command Handlers | Toss Auto-Trading Dev Journal #17 - Orbit - Space & ETF Investing

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top