You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DDD架构下交易机器人与模拟器的分层设计及命名咨询

Hey Roei, let's break down your DDD design questions and the multi-project reuse challenge step by step:

DDD Design Questions & Reuse Strategy

Your Core DDD Questions

1. Should the Trading Bot and Simulator Be in the Same Layer?

Absolutely—they belong in the same layer, and you were right to avoid putting the simulator in the Domain layer (that would violate ISP). Here's why:
Both the bot and simulator are use case orchestrators, not core business logic. The bot executes daily trade recommendations by coordinating domain services, while the simulator runs trading strategies against historical data to validate them. Neither holds core business rules; they just trigger and coordinate domain logic.

Your Simulator class is a perfect example of this:

class Simulator:
  def run(
    self,
    initial_money_amount: float,
    symbols: List[str],
    trading_strategy: TradingStrategy,
    date_range: Tuple[float, float]=(NOW-YEAR, NOW)
  ) -> SimulationResult:
    pass

It relies on domain components like TradingStrategy but doesn't define strategy logic itself. Placing it alongside the bot keeps your Domain layer focused on core business capabilities, respecting ISP.

2. UI Layer or Application Layer?

This should be the Application Layer, not UI. The "UI layer" typically refers to user-facing interfaces (like a web dashboard or CLI for human interaction), but your bot and simulator are automated executors of business use cases.

In standard DDD, the Application Layer is responsible for:

  • Orchestrating domain services to fulfill specific use cases (e.g., "execute daily trade recommendations" or "run strategy simulation")
  • Handling external triggers (scheduled jobs for the bot, CLI commands for the simulator)
  • Converting input/output between external systems and the domain model

Renaming this layer to Application Layer will align your design with DDD best practices and make its purpose clearer.

3. Current Design Flaws & Naming Optimizations

Let's break down gaps and tweaks to improve your design:

  • Flaw 1: Thin Entry Points, No Application Services
    Right now, your bot.py and simulator.py are directly calling domain services. Wrap each workflow in an Application Service (e.g., DailyTradeExecutionService, StrategySimulationService) to encapsulate use case logic (like fetching symbols, initializing repositories, coordinating services). This keeps entry points (main.py) thin and reusable.
  • Flaw 2: Tight Strategy Coupling
    Your RecommendationService contains trading_strategy_1/2, which violates the Open/Closed Principle (adding new strategies requires modifying the service). Instead, define a TradingStrategy interface in the Domain layer, then implement each strategy as a separate class (e.g., MovingAverageCrossoverStrategy, RSIStrategy). Inject the strategy into RecommendationService instead of hardcoding it.
  • Naming Optimization: Repository Clarity
    In your full DAL layer, SqlStocksRepository is okay, but add specificity if possible (e.g., PostgresStocksRepository if using Postgres). Ensure your domain interfaces (IStocksRepository, ISymbolsRepository) stay in the Domain layer—great call on including these already!
  • Naming Optimization: Service Clarity
    Rename StocksDataCollectionService to MarketDataFetchService to better reflect its purpose (it pulls data from external APIs, not just collects stock records). SimulationResult could become StrategySimulationResult for explicit clarity.

Multi-Project Reuse Strategy

Since the bot and simulator share core domain logic, structure them as separate projects with shared components using this approach:

  1. Extract a Shared Domain Core Package
    Create a standalone Python package (e.g., trading-domain-core) containing all pure Domain layer code:

    • Entities: Stock, Symbol
    • Interfaces: IStocksRepository, ISymbolsRepository, TradingStrategy
    • Domain Services: MarketDataFetchService, RecommendationService
      This package should have no external framework dependencies (no SQLAlchemy, no schedulers)—it's pure business logic.
  2. Build Separate Projects for Bot and Simulator

    • Trading Bot Project:
      • Depends on trading-domain-core
      • Contains Application Layer code: DailyTradeExecutionService, entry point main.py (with scheduler logic)
      • Contains DAL layer code: SqlStocksRepository, SqlSymbolsRepository (database-specific implementations)
    • Trading Simulator Project:
      • Depends on trading-domain-core
      • Contains Application Layer code: StrategySimulationService, entry points main.py and simulator.py
      • Can have its own data source implementation (e.g., HistoricalStocksRepository that reads from CSV files or a historical data API)
  3. Use Dependency Injection
    Inject concrete repository/strategy implementations into domain services in each project. For example:

    • In the bot, inject SqlStocksRepository into MarketDataFetchService
    • In the simulator, inject HistoricalStocksRepository into the same MarketDataFetchService
      This keeps domain logic decoupled from external systems, making reuse seamless.
  4. Shared Utility Package (Optional)
    If both projects use common utilities (date range handling, data validation, logging), extract these into a trading-utils package that both bot and simulator depend on.


内容的提问来源于stack exchange,提问作者Roei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 17:15:51