pyqqq-script 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. pyqqq3/__init__.py +15 -0
  2. pyqqq3/application/__init__.py +0 -0
  3. pyqqq3/application/backtest.py +213 -0
  4. pyqqq3/application/live.py +142 -0
  5. pyqqq3/application/messaging/__init__.py +5 -0
  6. pyqqq3/application/messaging/bus.py +38 -0
  7. pyqqq3/application/session.py +48 -0
  8. pyqqq3/application/store.py +87 -0
  9. pyqqq3/auth.py +28 -0
  10. pyqqq3/infra/__init__.py +0 -0
  11. pyqqq3/infra/broker/__init__.py +0 -0
  12. pyqqq3/infra/broker/kis.py +134 -0
  13. pyqqq3/infra/broker/mock.py +599 -0
  14. pyqqq3/infra/data/__init__.py +0 -0
  15. pyqqq3/infra/data/historical.py +159 -0
  16. pyqqq3/infra/data/symbols.py +49 -0
  17. pyqqq3/infra/presentation/__init__.py +9 -0
  18. pyqqq3/infra/presentation/cli_reporter.py +60 -0
  19. pyqqq3/infra/store/__init__.py +0 -0
  20. pyqqq3/infra/store/file.py +168 -0
  21. pyqqq3/infra/store/http.py +403 -0
  22. pyqqq3/infra/store/mongo.py +361 -0
  23. pyqqq3/model/__init__.py +0 -0
  24. pyqqq3/model/account.py +127 -0
  25. pyqqq3/model/execution/__init__.py +24 -0
  26. pyqqq3/model/execution/events.py +64 -0
  27. pyqqq3/model/execution/journal.py +132 -0
  28. pyqqq3/model/execution/order.py +32 -0
  29. pyqqq3/model/result.py +280 -0
  30. pyqqq3/model/symbol.py +39 -0
  31. pyqqq3/model/symbol_repository.py +31 -0
  32. pyqqq3/model/types.py +90 -0
  33. pyqqq3/strategy/__init__.py +11 -0
  34. pyqqq3/strategy/base.py +132 -0
  35. pyqqq3/strategy/series.py +101 -0
  36. pyqqq3/strategy/ta.py +269 -0
  37. pyqqq3/trading/__init__.py +0 -0
  38. pyqqq3/trading/broker.py +47 -0
  39. pyqqq3/trading/engine.py +122 -0
  40. pyqqq3/trading/feed.py +27 -0
  41. pyqqq_script-0.0.1.dist-info/METADATA +75 -0
  42. pyqqq_script-0.0.1.dist-info/RECORD +43 -0
  43. pyqqq_script-0.0.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,134 @@
1
+ """KISDomesticBroker — 한국투자증권 REST/Websocket 어댑터 (스켈레톤).
2
+
3
+ 실제 API 연동은 추후 작성한다. 이 파일은 Broker 계약 형태와
4
+ 이벤트 발행 헬퍼만 제공해 LiveTrading 이 Backtest 와 동일한 구조로
5
+ 조립될 수 있음을 보여준다.
6
+
7
+ 외부로 나가는 것 (이 어댑터의 책임):
8
+ buy/sell/cancel → KIS REST 주문 API
9
+ set_stop_loss/set_take_profit/set_trailing_stop → 로컬 상태
10
+
11
+ 외부에서 들어오는 것 (Account 에 반영될 이벤트):
12
+ OrderSubmitted — 주문 접수 응답
13
+ OrderRejected — 주문 거부 응답
14
+ FillExecuted — 체결 통보 (websocket)
15
+ CashDeposited — 초기 잔고 조회 응답
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import datetime as dt
21
+ import logging
22
+ from decimal import Decimal
23
+ from typing import TYPE_CHECKING, Callable
24
+
25
+ from pyqqq3.model.types import Bar, OrderSide, Position
26
+
27
+ if TYPE_CHECKING:
28
+ from pyqqq3.model.execution.events import ExecutionEvent
29
+ from pyqqq3.model.symbol import Symbol
30
+
31
+ _log = logging.getLogger("pyqqq3.broker.kis")
32
+
33
+
34
+ class KISDomesticBroker:
35
+ """한국투자증권 브로커 어댑터 (스켈레톤 / 미구현).
36
+
37
+ Attributes:
38
+ symbol: 단일 종목 전용 (향후 멀티심볼 확장 여지).
39
+ """
40
+
41
+ def __init__(
42
+ self,
43
+ symbol: "Symbol",
44
+ event_sink: "Callable[[ExecutionEvent], None]",
45
+ account_no: str = "",
46
+ ) -> None:
47
+ self._symbol = symbol
48
+ self._emit: Callable[[ExecutionEvent], None] = event_sink
49
+ self._account_no = account_no
50
+ self._seq = 0
51
+ self._stop_loss_pct: float | None = None
52
+ self._take_profit_pct: float | None = None
53
+ self._trailing_pct: float | None = None
54
+
55
+ # ------------------------------------------------------------------ Broker interface
56
+
57
+ def process(self, bar: Bar) -> None:
58
+ """실시간 모드에서는 no-op. 체결은 외부 이벤트로 들어온다."""
59
+ # 향후: 봉 단위 리스크 체크가 필요하면 여기에. 단, 실제 손절/익절 주문은
60
+ # 거래소에 미리 걸어두거나(OCO), websocket 에서 판단.
61
+
62
+ def buy(
63
+ self,
64
+ current_price: Decimal,
65
+ qty: int | None = None,
66
+ amount: int | None = None,
67
+ pct: float | None = None,
68
+ ) -> None:
69
+ raise NotImplementedError("KIS 주문 API 연동 필요")
70
+
71
+ def sell(
72
+ self,
73
+ current_price: Decimal,
74
+ qty: int | None = None,
75
+ pct: float | None = None,
76
+ ) -> None:
77
+ raise NotImplementedError("KIS 주문 API 연동 필요")
78
+
79
+ def set_stop_loss(self, pct: float) -> None:
80
+ self._stop_loss_pct = float(pct)
81
+
82
+ def set_take_profit(self, pct: float) -> None:
83
+ self._take_profit_pct = float(pct)
84
+
85
+ def set_trailing_stop(self, pct: float) -> None:
86
+ self._trailing_pct = float(pct)
87
+
88
+ def get_position(self, current_price: Decimal) -> Position:
89
+ raise NotImplementedError("Account 애그리게이트 조회로 위임 예정")
90
+
91
+ # ------------------------------------------------------------------ event emission helpers
92
+
93
+ def _next_seq(self) -> int:
94
+ self._seq += 1
95
+ return self._seq
96
+
97
+ def emit_cash_deposited(self, amount: Decimal) -> None:
98
+ """초기 잔고 조회 결과를 이벤트로 발행 (run 시작 시 1회)."""
99
+ from pyqqq3.model.execution.events import CashDeposited
100
+
101
+ self._emit(
102
+ CashDeposited(
103
+ occurred_at=dt.datetime.now(),
104
+ bar_index=0,
105
+ seq=self._next_seq(),
106
+ amount=amount,
107
+ )
108
+ )
109
+
110
+ def emit_fill(
111
+ self,
112
+ order_id: str,
113
+ side: OrderSide,
114
+ price: Decimal,
115
+ quantity: int,
116
+ commission: Decimal,
117
+ occurred_at: dt.datetime,
118
+ bar_index: int = 0,
119
+ ) -> None:
120
+ """체결 통보 (websocket callback) → 이벤트로 변환."""
121
+ from pyqqq3.model.execution.events import FillExecuted
122
+
123
+ self._emit(
124
+ FillExecuted(
125
+ occurred_at=occurred_at,
126
+ bar_index=bar_index,
127
+ seq=self._next_seq(),
128
+ order_id=order_id,
129
+ side=side,
130
+ price=price,
131
+ quantity=quantity,
132
+ commission=commission,
133
+ )
134
+ )