Files
trex-core/docs/project-structure.md
T

14 KiB

Trex Core Project Structure

  • Baseline Mode: mixed
  • Baseline Seed: .stage-pilot/bootstrap/baseline.yaml
  • Status: draft
  • Owner: project maintainers
  • Last Updated (KST): 2026-06-07 (BAT-012)
  • Source Discovery / Batch: bootstrap-baseline (pre-Discovery, 3-phase lifecycle 밖의 bootstrap 산출물)

Project Summary

  • trex 제품군의 공용 베이스로, 첫 도메인으로 trex-orbit 의 일일 거래 슬롯 생명주기(slot) 순수 도메인을 storage-agnostic 하게 이식한 코어다.

Primary Domain

  • 자동매매 일일 거래 슬롯 생명주기 도메인 (equity trading slot lifecycle)

Tech Stack

  • Python >=3.12
  • pyproject.toml 기반 패키지 (setuptools)
  • pytest (단위 테스트)
  • ruff (린트)
  • storage-agnostic 순수 도메인 (현재 in-memory repository, PostgreSQL/psycopg 는 향후 영속화 단계에서 도입 예정)

Primary Runtime

  • Type: daemon (sync + thread, no HTTP) + library (slot 도메인)
  • Entry Points:
    • trex-core-daemon (console_script → trex_core.runtime.daemon:main) :: 슬롯 코어 데몬 — migrate+preallocate+reconcile 후 7 백그라운드 스레드(intent RPC consumer / snapshot RPC consumer / control RPC consumer / snapshot scheduler / execution / ledger / safety-sell) 기동, RabbitMQ messaging 으로 전략 모듈과 통신 (BAT-002 + BAT-007 + BAT-008 + BAT-011 + BAT-012)
    • trex-core (console_script → trex_core.runtime.cli:main) :: 운영 CLI (pause / resume / paused) (BAT-008)
    • RabbitMQ trex.snapshot.req / trex.intent.req / trex.pause.req / trex.events :: 매수·매도 전략 데몬과의 transport (docs/interface-contract.md)
    • SlotService / SlotRepository (Protocol) :: in-process 도메인 서비스 + 저장소 경계(라이브러리 사용)
    • MessagingTransport (Protocol) :: transport 추상화 (RabbitMQ / InMemory stub)
    • PortfolioHubReadPort (Protocol) :: portfolio-hub universe read 경계 (BAT-008)

Purpose

  • This document is the current approved repository and package structure baseline.
  • It is a cross-cutting reference document for Discovery, REQ, Batch Design, Batch Verification, and implementation updates.

Scope

  • Covers the top-level repository layout and package/module boundaries.
  • Does not duplicate detailed business rules, acceptance criteria, or implementation-only function signatures.

Top-Level Structure

.
├── .github/                      # Copilot instructions + StagePilot skill entrypoints
│   ├── instructions/
│   └── skills/
├── .stage-pilot/                 # StagePilot 도구/템플릿/부트스트랩 seed
│   ├── bootstrap/
│   │   └── baseline.yaml
│   └── templates/
├── docs/                         # SDLC baseline 문서 + active index
│   ├── batches/index.md
│   ├── discovery/index.md
│   ├── releases/index.md
│   ├── srs/index.md
│   ├── data-model.md
│   ├── interface-contract.md
│   ├── project-structure.md
│   └── runtime-flows.md
├── CLAUDE.md                     # SDLC governance instructions
├── pyproject.toml                # 패키지 메타(배포명 trex-core) + console_scripts(trex-core-daemon) + deps
├── trex_core/
│   ├── __init__.py
│   ├── domain/slot/              # slot 순수 도메인 (BAT-001, 무의존)
│   │   ├── __init__.py · state.py · models.py(+EXPECTED_SLOT_FIELDS) · errors.py
│   │   ├── repository.py(Protocol) · service.py · in_memory_repository.py
│   ├── application/              # 유스케이스 (BAT-002, BAT-004, BAT-006, BAT-007, BAT-008)
│   │   ├── ports.py              # IntentStore Protocol
│   │   ├── intents.py            # IntentService / BuyIntent / SellIntent / IntentDecision
│   │   ├── broker_port.py        # BrokerPort + OrderRequest/OrderAck/FillStatus + BalanceItem + calculate_fee (BAT-004/BAT-006/BAT-008)
│   │   ├── execution.py          # ExecutionService (dispatch·poll·transition·reconcile + ledger enqueue + event emit hook)
│   │   ├── ledger_port.py        # LedgerPort + LedgerTrade/LedgerWriteResult/예외 (BAT-006)
│   │   ├── ledger_outbox.py      # LedgerOutbox Protocol + LedgerWriter + InMemoryLedgerOutbox (BAT-006)
│   │   ├── messaging.py          # MessagingTransport Protocol + DTO + TransportHealth (BAT-007)
│   │   ├── messaging_handlers.py # intent/snapshot/pause RPC handlers (+update_thresholds REQ-040) + slot event payload builder (BAT-007/BAT-008/BAT-011)
│   │   ├── portfolio.py          # PortfolioHubReadPort + SnapshotStore + PauseStore + envelope builder (BAT-008)
│   │   ├── reconciliation.py     # reconcile_positions (hub ↔ broker symbol-aggregate) (BAT-008)
│   │   ├── snapshot_scheduler.py # SnapshotScheduler — daily fetch + swap + reconcile (BAT-008)
│   │   ├── watchdog.py           # WatchdogStore — per-slot last_seen_at + expiry/grace 판정 (BAT-010 / REQ-034)
│   │   ├── safety_sell.py        # SafetySellService — forced_close / stop-loss·take-profit / 장 마감 트리거 (BAT-011 / REQ-037~039)
│   │   └── killswitch.py         # KillSwitchService — 범위별 holding 즉시 청산 + day-scoped 제외 (BAT-012 / REQ-045)
│   ├── adapters/                 # 인프라 어댑터 (BAT-002, BAT-004, BAT-006, BAT-007, BAT-008)
│   │   ├── broker/               # paper.py(결정적 async 더블 + 현재가 stub) · kis.py(KIS Open API + 잔고조회 + 현재가 polling)  (BAT-004/BAT-008/BAT-011)
│   │   ├── ledger/               # in_memory.py(stub) · portfolio_hub.py(HTTP 어댑터)  (BAT-006)
│   │   ├── messaging/            # topology.py · in_memory.py(stub) · rabbitmq.py(pika 동기)  (BAT-007)
│   │   ├── portfolio/            # hub_read.py(HTTP) · stub_read.py(stub) · pause_store.py(Postgres) · killswitch_store.py(day-scoped, BAT-012) (BAT-008)
│   │   └── persistence/          # postgresql.py(+PostgreSQLLedgerOutbox) · in_memory_intent_store.py · migrate.py · sql/(001_…, 002_create_ledger_outbox.sql, 003_create_snapshot_pause.sql, 004_add_price_thresholds.sql, 005_create_killswitch_exclusion.sql)
│   └── runtime/                  # 데몬 (BAT-002, BAT-004, BAT-006, BAT-007, BAT-008)
│       ├── config.py             # DaemonConfig + KISConfig + PortfolioHubConfig + RabbitMQConfig + SnapshotScheduleConfig + SafetySellConfig(TREX_WATCHDOG_*/FORCED_CLOSE/STOP_LOSS_POLL/MARKET_CLOSE) (env)
│       ├── daemon.py             # Daemon class: setup(migrate/preallocate/reconcile/declare-topology) + 7 worker threads (execution·ledger·intent-rpc·snapshot-rpc·control-rpc·snapshot-scheduler·safety-sell) + WatchdogStore + KillSwitchService + graceful shutdown
│       └── cli.py                # trex-core CLI: pause/resume/paused subcommands (BAT-008 / REQ-032)
└── tests/
    ├── domain/slot/              # test_state / test_service / test_contract
    ├── domain/                   # test_domain_import_sweep (NFR-1 가드, BAT-006/BAT-007)
    ├── application/              # test_intent_concurrency · test_execution · test_execution_ledger · test_ledger_outbox · test_messaging_intent_consumer · test_messaging_snapshot_consumer · test_messaging_event_publisher
    ├── runtime/                  # test_config_dotenv · test_daemon_no_http_surface (BAT-007 HTTP 표면 0 회귀 가드)
    └── adapters/{broker,ledger,messaging,persistence}/  # paper/KIS · in_memory/portfolio-hub ledger · stub/RabbitMQ transport (게이트) · PG repo/migration/outbox

참고: domain(BAT-001)은 무의존 코어. application/adapters/runtime 은 BAT-002 에서 추가, BAT-004 에서 broker/execution 레이어 확장, BAT-006 에서 ledger 레이어 추가, BAT-007 에서 messaging 레이어(application MessagingTransport + adapters/messaging + sync+thread 데몬) 추가와 HTTP 어댑터 제거. 외부 의존(psycopg/httpx/redis/pika)은 adapters/runtime 에만 격리(NFR-1, import 스윕으로 강제). 브로커 주문은 BrokerPort 단일 세션(불변식 B), 슬롯 쓰기는 SlotService 단일 writer(불변식 A), ledger 기록은 집행 경로 단일 주체(NFR-3), 메시지 transport 는 MessagingTransport 단일 경계.

Package / Module Responsibilities

  • trex_core/domain/slot/
    • 슬롯 생명주기 순수 도메인. 6 상태 머신(state.py), 데이터 모델 + 컬럼 계약(models.py, EXPECTED_SLOT_FIELDS 포함), 예외(errors.py), 저장소 계약(repository.py Protocol), 도메인 서비스(service.py), in-memory 구현(in_memory_repository.py).
    • 외부 의존 0 — stdlib 와 패키지 내부 참조만 사용(정적 import 스윕으로 확인됨).
  • tests/domain/slot/
    • 상태머신/서비스 단위 테스트(test_state, test_service) + 컬럼 계약 가드(test_contract). InMemorySlotRepository 기반으로 실제 DB 없이 검증.
  • docs/
    • SDLC baseline(구조/흐름/인터페이스/데이터 모델) 및 active index(discovery/srs/batches/releases).
  • pyproject.toml
    • 패키지 메타데이터(배포명 trex-core, requires-python >=3.12), dev 의존성(pytest/ruff), pytest/ruff 설정.

Dependency Rules

  • 순수 도메인(trex_core/domain/slot/)은 저장소 구현, 브로커, 네트워크, CLI 등 인프라에 직접 의존하지 않는다.
  • 저장소 접근은 오직 SlotRepository Protocol 을 통해서만 이뤄지고 구현체는 주입된다.
  • 인프라(향후 PostgreSQL 구현, CLI, config)는 도메인을 의존할 수 있으나 그 역은 금지한다.

Shared Boundaries

  • SlotRepository Protocol 이 도메인 ↔ 저장소 사이의 단일 경계다.
  • SLOT_ADVISORY_LOCK_ID 상수가 모든 상태 변경 직렬화의 공유 기준점이다.

Current Gaps / Planned Changes

  • 영속화 구현체(PostgreSQL repository)와 SQL 스키마/마이그레이션은 이번 범위 밖 — 향후 도입.
  • CLI / 설정(config) 표면 없음(trex-orbit 의 trex slot CLI 미이식).
  • 패키지 네임스페이스는 trex_core.domain.slot 으로 확정(dcy-001 OQ-1, 배포명 trex-core).
  • 컬럼 계약 드리프트는 EXPECTED_SLOT_FIELDS + test_contract.py 로 강제(DB-side 검사는 영속화 반복 인계).

Update Triggers

  • Update this document when package boundaries change.
  • Update this document when new top-level runtime or domain modules are added.
  • Update this document when a batch changes the approved structure baseline.

Change Log

  • 2026-06-03 :: bootstrap-baseline 으로 초기 구조 baseline 생성(mixed: trex-orbit 코드 관찰 + 이관 계획 선언).
  • 2026-06-03 :: dcy-001 OQ-1 결정 반영 — planned 네임스페이스를 app/ → trex_core/ 로 정정(배포명 trex-core).
  • 2026-06-03 :: BAT-001 이식 완료 반영 — trex_core/·tests/·pyproject.toml planned→실제 정합(REQ-004).
  • 2026-06-03 :: BAT-002 — application/adapters/runtime 레이어(데몬+HTTP API+PostgreSQL) 추가, Primary Runtime=daemon+library(REQ-005~009).
  • 2026-06-04 :: BAT-004 — 브로커 집행 레이어 반영(BrokerPort/paper·KIS 어댑터, execution 루프, broker_order_id 실행큐·멱등, reconciliation) (REQ-011~015).
  • 2026-06-04 :: BAT-006 — ledger 레이어 추가(application LedgerPort/LedgerOutbox, adapters/ledger in_memory·portfolio_hub, persistence PostgreSQLLedgerOutbox + 002 마이그레이션, runtime ledger writer 루프, FillStatus 확장, NFR-1 import 스윕) (REQ-017~020).
  • 2026-06-05 :: BAT-007 — transport 전환(adapters/api/ 제거, application/messaging.py + application/messaging_handlers.py 신설, adapters/messaging/ 신설(topology/in_memory/rabbitmq), runtime/daemon 을 sync+thread 4 스레드 구조로 재구성, RabbitMQConfig + TREX_RABBITMQ_URL env, TREX_API_HOST/TREX_API_PORT 폐기, fastapi/uvicorn 의존 제거 + pika 도입, NFR-1 import 스윕에 pika/messaging 추가, HTTP 표면 0 회귀 가드) (REQ-021~026).
  • 2026-06-06 :: BAT-008 — portfolio-hub 스냅샷 read 레이어 추가(application/portfolio.py + application/reconciliation.py + application/snapshot_scheduler.py 신설, adapters/portfolio/ 신설(hub_read/stub_read/pause_store), BrokerPort.get_balance() 확장 + paper/KIS 구현, messaging_handlers 에 snapshot envelope + pause RPC 추가, runtime/daemon 을 6 스레드로 확장(pause-rpc + snapshot-scheduler), SnapshotScheduleConfig + TREX_SNAPSHOT_* env, runtime/cli.py + trex-core 콘솔 스크립트, 003_create_snapshot_pause.sql 마이그레이션, NFR-1 import 스윕 유지) (REQ-027~033; REQ-030 옵션 D 는 portfolio-hub#8 배포 후 별도 구현).
  • 2026-06-07 :: BAT-010 — safety-sell 기반 인프라(application/watchdog.py WatchdogStore 신설, Slot 에 stop_loss_price/take_profit_price 필드 + 004_add_price_thresholds.sql additive 마이그레이션, SlotService.sell() 자율 매도 내부 경로, make_snapshot_rpc_handler 워치독 갱신, SafetySellConfig env 5종 파싱) (REQ-034~036, 041).
  • 2026-06-07 :: BAT-011 — safety-sell 트리거 레이어(application/safety_sell.py SafetySellService 신설 — forced_close/stop-loss·take-profit/장 마감, BrokerPort.get_current_price() + KIS inquire-price(FHKST01010100, CHG-04 정정)·paper stub, SlotService.update_thresholds() + intent RPC update_thresholds 액션, runtime/daemon 을 7 스레드로 확장(trex-safety-sell) + WatchdogStore 배선) (REQ-037~040, 042).
  • 2026-06-07 :: BAT-012 — 비상 정지/kill-switch(trex.pause.req→trex.control.req 제어 채널 + action dispatch, application/killswitch.py KillSwitchService + adapters/portfolio/killswitch_store.py + 005_create_killswitch_exclusion.sql day-scoped 제외, snapshot masking 에 killswitch_today 추가, make_control_rpc_handler + kill_switch/resume_kill_switch, daemon control consumer 전환) (REQ-043~047).