pyqqq-script 0.0.1__tar.gz → 0.0.2__tar.gz
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.
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/PKG-INFO +9 -17
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/README.md +8 -16
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyproject.toml +5 -1
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/application/backtest.py +8 -8
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/application/live.py +13 -13
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/application/messaging/bus.py +3 -3
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/application/session.py +2 -2
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/application/store.py +8 -8
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/auth.py +3 -3
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/broker/kis.py +3 -3
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/broker/mock.py +62 -62
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/data/historical.py +2 -2
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/data/symbols.py +2 -2
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/presentation/__init__.py +2 -2
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/presentation/cli_reporter.py +3 -3
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/store/file.py +2 -2
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/store/http.py +5 -5
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/store/mongo.py +3 -3
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/account.py +5 -5
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/execution/journal.py +5 -5
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/result.py +1 -1
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/symbol.py +7 -7
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/symbol_repository.py +3 -3
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/types.py +1 -1
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/strategy/__init__.py +1 -1
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/strategy/base.py +69 -11
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/strategy/series.py +4 -4
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/strategy/ta.py +203 -4
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/trading/broker.py +4 -4
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/trading/engine.py +7 -7
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/application/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/application/messaging/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/broker/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/data/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/infra/store/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/execution/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/execution/events.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/model/execution/order.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/trading/__init__.py +0 -0
- {pyqqq_script-0.0.1 → pyqqq_script-0.0.2}/pyqqq3/trading/feed.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyqqq-script
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2
|
|
4
4
|
Summary: Pine Script-style trading library built on top of pyqqq
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: PyQQQ team
|
|
@@ -23,27 +23,25 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
**"우리는 누구나 자신의 투자 아이디어를 현실로 만들 수 있다고 믿습니다."**
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## 환경설정
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
발급받은 API Key는 환경 변수로 설정해 사용합니다.
|
|
28
|
+
### 1.1 설치
|
|
31
29
|
|
|
32
30
|
```bash
|
|
33
|
-
|
|
31
|
+
pip install pyqqq-script
|
|
34
32
|
```
|
|
35
33
|
|
|
34
|
+
### 1.2 API Key 발급
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
[PyQQQ](pyqqq.net)는 금융 데이터 분석과 자동화된 거래 전략을 제공하는 플랫폼입니다. 회원가입 후 API Key 를 발급받아 환경변수를 설정합니다. 보다 자세한 안내는 [공식 가이드](https://docs.pyqqq.net/getting_started/install.html) 문서를 참고하세요.
|
|
38
37
|
|
|
39
38
|
```bash
|
|
40
|
-
|
|
39
|
+
export PYQQQ_API_KEY="발급받은_API_KEY"
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
|
|
44
42
|
## Quick Start
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
몇 줄의 코드로 동작하는 백테스트 코드를 보여드리겠습니다.
|
|
47
45
|
|
|
48
46
|
```python
|
|
49
47
|
from pyqqq3 import Backtest, Strategy, ta
|
|
@@ -51,6 +49,7 @@ from pyqqq3.infra.presentation import print_result
|
|
|
51
49
|
|
|
52
50
|
|
|
53
51
|
class Simple(Strategy):
|
|
52
|
+
|
|
54
53
|
def next(self):
|
|
55
54
|
sma5 = ta.sma(self.close, 5)
|
|
56
55
|
sma20 = ta.sma(self.close, 20)
|
|
@@ -65,11 +64,4 @@ bt = Backtest(strategy=Simple, symbol="005930", start="2026-04-01", end="2026-04
|
|
|
65
64
|
print_result(bt.run())
|
|
66
65
|
```
|
|
67
66
|
|
|
68
|
-
> 실제로 동작하는 전략들은 `examples/` 디렉터리를 참고하세요.
|
|
69
|
-
|
|
70
|
-
실행:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
python examples/mean_reversion_rsi_bb.py
|
|
74
|
-
```
|
|
75
67
|
|
|
@@ -4,27 +4,25 @@
|
|
|
4
4
|
**"우리는 누구나 자신의 투자 아이디어를 현실로 만들 수 있다고 믿습니다."**
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 환경설정
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
발급받은 API Key는 환경 변수로 설정해 사용합니다.
|
|
9
|
+
### 1.1 설치
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
|
-
|
|
12
|
+
pip install pyqqq-script
|
|
15
13
|
```
|
|
16
14
|
|
|
15
|
+
### 1.2 API Key 발급
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
[PyQQQ](pyqqq.net)는 금융 데이터 분석과 자동화된 거래 전략을 제공하는 플랫폼입니다. 회원가입 후 API Key 를 발급받아 환경변수를 설정합니다. 보다 자세한 안내는 [공식 가이드](https://docs.pyqqq.net/getting_started/install.html) 문서를 참고하세요.
|
|
19
18
|
|
|
20
19
|
```bash
|
|
21
|
-
|
|
20
|
+
export PYQQQ_API_KEY="발급받은_API_KEY"
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
|
|
25
23
|
## Quick Start
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
몇 줄의 코드로 동작하는 백테스트 코드를 보여드리겠습니다.
|
|
28
26
|
|
|
29
27
|
```python
|
|
30
28
|
from pyqqq3 import Backtest, Strategy, ta
|
|
@@ -32,6 +30,7 @@ from pyqqq3.infra.presentation import print_result
|
|
|
32
30
|
|
|
33
31
|
|
|
34
32
|
class Simple(Strategy):
|
|
33
|
+
|
|
35
34
|
def next(self):
|
|
36
35
|
sma5 = ta.sma(self.close, 5)
|
|
37
36
|
sma20 = ta.sma(self.close, 20)
|
|
@@ -46,10 +45,3 @@ bt = Backtest(strategy=Simple, symbol="005930", start="2026-04-01", end="2026-04
|
|
|
46
45
|
print_result(bt.run())
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
> 실제로 동작하는 전략들은 `examples/` 디렉터리를 참고하세요.
|
|
50
|
-
|
|
51
|
-
실행:
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
python examples/mean_reversion_rsi_bb.py
|
|
55
|
-
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "pyqqq-script"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.2"
|
|
4
4
|
description = "Pine Script-style trading library built on top of pyqqq"
|
|
5
5
|
authors = ["PyQQQ team <pyqqq.cs@gmail.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -22,6 +22,10 @@ ta = ">=0.11"
|
|
|
22
22
|
ruff = ">=0.6"
|
|
23
23
|
mongomock = ">=4.1"
|
|
24
24
|
|
|
25
|
+
[tool.poetry.group.docs.dependencies]
|
|
26
|
+
mkdocs-material = ">=9.5"
|
|
27
|
+
mkdocstrings = { version = ">=0.26", extras = ["python"] }
|
|
28
|
+
|
|
25
29
|
[build-system]
|
|
26
30
|
requires = ["poetry-core"]
|
|
27
31
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Backtest — 과거 데이터 시뮬레이션 파사드.
|
|
2
2
|
|
|
3
|
-
HistoricalDataFeed + MockBroker + TradingEngine 을
|
|
3
|
+
HistoricalDataFeed + MockBroker + TradingEngine 을 조립합니다.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
@@ -29,7 +29,7 @@ if TYPE_CHECKING:
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class Backtest:
|
|
32
|
-
"""과거 OHLCV DataFrame 으로 전략을
|
|
32
|
+
"""과거 OHLCV DataFrame 으로 전략을 시뮬레이션합니다.
|
|
33
33
|
|
|
34
34
|
두 가지 모드:
|
|
35
35
|
1. DataFrame 직접 제공 (테스트용):
|
|
@@ -39,10 +39,10 @@ class Backtest:
|
|
|
39
39
|
bt = Backtest(strategy=RSI_BB, symbol="005930",
|
|
40
40
|
start="2025-01-01", end="2025-12-31", capital=10_000_000)
|
|
41
41
|
|
|
42
|
-
``symbol`` 이 주어지면 ``symbol_repo`` 를 통해 즉시 메타데이터를
|
|
43
|
-
종목이 존재하지 않으면 ``SymbolNotFound`` 가
|
|
42
|
+
``symbol`` 이 주어지면 ``symbol_repo`` 를 통해 즉시 메타데이터를 하이드레이트합니다.
|
|
43
|
+
종목이 존재하지 않으면 ``SymbolNotFound`` 가 발생합니다.
|
|
44
44
|
|
|
45
|
-
session_store 를 지정하면 운용 이력을
|
|
45
|
+
session_store 를 지정하면 운용 이력을 기록합니다:
|
|
46
46
|
from pyqqq3.infra.store.file import FileStore
|
|
47
47
|
bt = Backtest(..., session_store=FileStore())
|
|
48
48
|
"""
|
|
@@ -173,12 +173,12 @@ _FRAMEWORK_ATTRS = frozenset(
|
|
|
173
173
|
|
|
174
174
|
|
|
175
175
|
def _extract_strategy_params(strategy: "Strategy") -> dict:
|
|
176
|
-
"""전략 인스턴스에서 직렬화 가능한 파라미터를
|
|
176
|
+
"""전략 인스턴스에서 직렬화 가능한 파라미터를 추출합니다.
|
|
177
177
|
|
|
178
178
|
클래스 레벨 변수와 ``init()`` 안에서 ``self.X = ...`` 로 선언한 인스턴스 변수를
|
|
179
|
-
모두
|
|
179
|
+
모두 포함합니다. 같은 이름이 양쪽에 있으면 인스턴스 값이 우선합니다 (Python 속성
|
|
180
180
|
lookup 과 동일). 엔진이 주입하는 framework 속성(open/high/low/close/volume,
|
|
181
|
-
bar_index, time, is_last_bar)과 underscore-prefixed 내부 속성은
|
|
181
|
+
bar_index, time, is_last_bar)과 underscore-prefixed 내부 속성은 제외합니다.
|
|
182
182
|
"""
|
|
183
183
|
try:
|
|
184
184
|
params: dict = {}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""LiveTrading — 실시간 트레이딩 파사드.
|
|
2
2
|
|
|
3
|
-
Backtest 와 동일한 조립 구조를
|
|
3
|
+
Backtest 와 동일한 조립 구조를 씁니다:
|
|
4
4
|
DataFeed + Broker + EventBus + Account + ExecutionJournal → TradingEngine
|
|
5
5
|
|
|
6
|
-
차이는 Broker/DataFeed 의
|
|
7
|
-
이 파일은 DI 배선과 lifecycle 만
|
|
6
|
+
차이는 Broker/DataFeed 의 구현체뿐입니다 (KISDomesticBroker + RealtimeDataFeed).
|
|
7
|
+
이 파일은 DI 배선과 lifecycle 만 담당합니다.
|
|
8
8
|
|
|
9
9
|
session_store 가 주입되면 EventBus 에 streaming sink 를 붙여 이벤트가
|
|
10
|
-
발생하는 즉시 store 로
|
|
11
|
-
체결 이력이
|
|
10
|
+
발생하는 즉시 store 로 흘려보냅니다 — 프로세스가 중간에 죽어도 그 시점까지의
|
|
11
|
+
체결 이력이 보존됩니다.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
from __future__ import annotations
|
|
@@ -37,20 +37,20 @@ if TYPE_CHECKING:
|
|
|
37
37
|
class LiveTrading:
|
|
38
38
|
"""실시간 트레이딩 파사드.
|
|
39
39
|
|
|
40
|
-
브로커와 데이터 피드는 호출자가 직접
|
|
41
|
-
수신한 체결/거부 이벤트를 ``event_sink`` 로 발행해야
|
|
42
|
-
LiveTrading 은 EventBus 를 통해 이를 Journal + Account 로 fan-out
|
|
40
|
+
브로커와 데이터 피드는 호출자가 직접 주입합니다. 브로커는 외부 거래소로부터
|
|
41
|
+
수신한 체결/거부 이벤트를 ``event_sink`` 로 발행해야 합니다 (Broker 규약).
|
|
42
|
+
LiveTrading 은 EventBus 를 통해 이를 Journal + Account 로 fan-out 합니다.
|
|
43
43
|
|
|
44
|
-
종목은 진입 시점에 ``symbol_repo.require()`` 로 즉시
|
|
45
|
-
존재하지 않는 종목 코드는 ``SymbolNotFound`` 로
|
|
44
|
+
종목은 진입 시점에 ``symbol_repo.require()`` 로 즉시 검증·하이드레이트합니다.
|
|
45
|
+
존재하지 않는 종목 코드는 ``SymbolNotFound`` 로 거부됩니다.
|
|
46
46
|
|
|
47
47
|
Args:
|
|
48
48
|
strategy: Strategy 서브클래스 타입.
|
|
49
49
|
data_feed: 실시간 DataFeed 구현체.
|
|
50
50
|
broker_factory: ``event_sink`` 를 받아 Broker 를 반환하는 팩토리.
|
|
51
|
-
symbol: 거래 종목 코드 (raw str). 즉시 ``Symbol`` 로
|
|
51
|
+
symbol: 거래 종목 코드 (raw str). 즉시 ``Symbol`` 로 하이드레이트됩니다.
|
|
52
52
|
symbol_repo: 종목 메타데이터 조회용 Repository. 미주입 시
|
|
53
|
-
``DomesticRepository`` 가
|
|
53
|
+
``DomesticRepository`` 가 사용됩니다.
|
|
54
54
|
session_store: 운용 이력 저장소 (선택).
|
|
55
55
|
"""
|
|
56
56
|
|
|
@@ -97,7 +97,7 @@ class LiveTrading:
|
|
|
97
97
|
|
|
98
98
|
session_id = new_session_id()
|
|
99
99
|
# broker 생성 시 CashDeposited 가 emit 되므로 session start 와 sink 구독은
|
|
100
|
-
# broker_factory 호출 *전*에 끝나야
|
|
100
|
+
# broker_factory 호출 *전*에 끝나야 합니다.
|
|
101
101
|
session = Session(
|
|
102
102
|
session_id=session_id,
|
|
103
103
|
kind="live",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""EventBus — 동기 in-process fanout.
|
|
2
2
|
|
|
3
3
|
브로커가 publish 한 ExecutionEvent 를 구독자(journal, Account 등)에게
|
|
4
|
-
순차적으로
|
|
4
|
+
순차적으로 전달합니다. Phase 1 단계에서는 단일 스레드, 동기 실행을 가정합니다.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
@@ -16,8 +16,8 @@ EventHandler = Callable[[ExecutionEvent], None]
|
|
|
16
16
|
class EventBus:
|
|
17
17
|
"""동기 이벤트 fanout.
|
|
18
18
|
|
|
19
|
-
한 번에 하나의 이벤트를 등록된 모든 핸들러에게 순차
|
|
20
|
-
구독자 등록 순서대로 실행되며, 한 핸들러 예외가 다음 핸들러 실행을
|
|
19
|
+
한 번에 하나의 이벤트를 등록된 모든 핸들러에게 순차 전달합니다.
|
|
20
|
+
구독자 등록 순서대로 실행되며, 한 핸들러 예외가 다음 핸들러 실행을 막습니다
|
|
21
21
|
(journal / Account 의 일관성 확보를 위해 의도된 동작).
|
|
22
22
|
|
|
23
23
|
Usage:
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
도메인 라이프사이클 ``Strategy → Session → SessionReport`` 의 가운데 단계로,
|
|
4
4
|
backtest/paper/live 를 아우르는 운용 인스턴스의 식별자·전략·심볼·기간·엔진설정을
|
|
5
|
-
담는 경계 DTO 다. ``SessionStore`` 가 이 타입들을 키로
|
|
5
|
+
담는 경계 DTO 다. ``SessionStore`` 가 이 타입들을 키로 영속화합니다.
|
|
6
6
|
|
|
7
7
|
심볼은 ``Symbol`` 객체로 보유하며, 영속화 어댑터(MongoStore/FileStore)는
|
|
8
8
|
직렬화 시 ``str(symbol.code)`` 로 변환하고 역직렬화 시 ``SymbolRepository`` 로
|
|
9
|
-
|
|
9
|
+
하이드레이트합니다.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""SessionStore — 운용 단위 저장/조회 인터페이스 (application 포트).
|
|
2
2
|
|
|
3
|
-
저장은 stream API 로 통일되어
|
|
3
|
+
저장은 stream API 로 통일되어 있습니다 — backtest 든 live 든 호출 패턴은 같습니다:
|
|
4
4
|
|
|
5
5
|
sid = store.start(session)
|
|
6
6
|
store.append_events(sid, events) # 0회 이상, 임의 배치 크기
|
|
7
7
|
store.finalize(sid, stats)
|
|
8
8
|
|
|
9
9
|
backtest 는 ``append_events`` 를 한 번에 모든 이벤트로 호출하고, live 는
|
|
10
|
-
EventBus 에 sink 를 붙여 이벤트마다(또는 배치 단위로)
|
|
11
|
-
구현체는 호출자가 backtest 인지 live 인지 알 필요가
|
|
10
|
+
EventBus 에 sink 를 붙여 이벤트마다(또는 배치 단위로) 호출합니다.
|
|
11
|
+
구현체는 호출자가 backtest 인지 live 인지 알 필요가 없습니다.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
from __future__ import annotations
|
|
@@ -29,7 +29,7 @@ class StoreLevel(Enum):
|
|
|
29
29
|
FillExecuted, RiskTriggered) 를 그대로 저장.
|
|
30
30
|
- FILLED: 체결 이벤트만 (FillExecuted, RiskTriggered) 저장. MVP 웹 뷰가
|
|
31
31
|
필요로 하는 최소 페이로드. 초기 자본은 ``Session.engine_config.capital``
|
|
32
|
-
에 이미 들어 있어 별도 보존이 필요
|
|
32
|
+
에 이미 들어 있어 별도 보존이 필요 없습니다.
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
35
|
FULL = "full"
|
|
@@ -54,20 +54,20 @@ class SessionStore(Protocol):
|
|
|
54
54
|
"""운용 정의·통계·이벤트 로그를 저장하고 조회하는 인터페이스.
|
|
55
55
|
|
|
56
56
|
write-only 싱크(파일)는 start/append_events/finalize 만 구현하고
|
|
57
|
-
load/list/delete 는 NotImplementedError 를
|
|
57
|
+
load/list/delete 는 NotImplementedError 를 올립니다.
|
|
58
58
|
"""
|
|
59
59
|
|
|
60
60
|
def start(self, session: Session) -> str:
|
|
61
61
|
"""session 을 시작 상태로 저장하고 session_id 반환. 동일 id 재호출 시
|
|
62
|
-
prior events 는 idempotent 하게
|
|
62
|
+
prior events 는 idempotent 하게 초기화됩니다."""
|
|
63
63
|
...
|
|
64
64
|
|
|
65
65
|
def append_events(
|
|
66
66
|
self, session_id: str, events: "list[ExecutionEvent]"
|
|
67
67
|
) -> None:
|
|
68
68
|
"""events 를 append. 빈 리스트는 no-op. 호출자는 임의 배치 크기로
|
|
69
|
-
여러 번 호출할 수
|
|
70
|
-
|
|
69
|
+
여러 번 호출할 수 있습니다. 구현체는 ``StoreLevel`` 에 따라 내부적으로
|
|
70
|
+
필터링합니다."""
|
|
71
71
|
...
|
|
72
72
|
|
|
73
73
|
def finalize(self, session_id: str, stats: dict[str, float]) -> None:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""API 키 노출 및 검증.
|
|
2
2
|
|
|
3
|
-
pyqqq 의 키 해석 정책(메모리 → env → ~/.qred)을 그대로
|
|
4
|
-
사용자는 pyqqq import 없이 ``pyqqq3.set_api_key`` 만으로 키를 주입할 수
|
|
3
|
+
pyqqq 의 키 해석 정책(메모리 → env → ~/.qred)을 그대로 따릅니다.
|
|
4
|
+
사용자는 pyqqq import 없이 ``pyqqq3.set_api_key`` 만으로 키를 주입할 수 있습니다.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
@@ -13,7 +13,7 @@ get_api_key = pyqqq.get_api_key
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def ensure_api_key() -> None:
|
|
16
|
-
"""외부 pyqqq API 호출 직전 키가 해석 가능한지
|
|
16
|
+
"""외부 pyqqq API 호출 직전 키가 해석 가능한지 확인합니다.
|
|
17
17
|
|
|
18
18
|
Raises:
|
|
19
19
|
RuntimeError: ``pyqqq.get_api_key()`` 가 None 인 경우.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""KISDomesticBroker — 한국투자증권 REST/Websocket 어댑터 (스켈레톤).
|
|
2
2
|
|
|
3
|
-
실제 API 연동은 추후
|
|
3
|
+
실제 API 연동은 추후 작성합니다. 이 파일은 Broker 계약 형태와
|
|
4
4
|
이벤트 발행 헬퍼만 제공해 LiveTrading 이 Backtest 와 동일한 구조로
|
|
5
|
-
조립될 수 있음을
|
|
5
|
+
조립될 수 있음을 보여줍니다.
|
|
6
6
|
|
|
7
7
|
외부로 나가는 것 (이 어댑터의 책임):
|
|
8
8
|
buy/sell/cancel → KIS REST 주문 API
|
|
@@ -55,7 +55,7 @@ class KISDomesticBroker:
|
|
|
55
55
|
# ------------------------------------------------------------------ Broker interface
|
|
56
56
|
|
|
57
57
|
def process(self, bar: Bar) -> None:
|
|
58
|
-
"""실시간 모드에서는 no-op. 체결은 외부 이벤트로
|
|
58
|
+
"""실시간 모드에서는 no-op. 체결은 외부 이벤트로 들어옵니다."""
|
|
59
59
|
# 향후: 봉 단위 리스크 체크가 필요하면 여기에. 단, 실제 손절/익절 주문은
|
|
60
60
|
# 거래소에 미리 걸어두거나(OCO), websocket 에서 판단.
|
|
61
61
|
|