market-wave 0.1.0__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.
- market_wave-0.1.0/.github/workflows/workflow.yml +40 -0
- market_wave-0.1.0/.gitignore +6 -0
- market_wave-0.1.0/LICENSE +21 -0
- market_wave-0.1.0/PKG-INFO +196 -0
- market_wave-0.1.0/README.ko.md +167 -0
- market_wave-0.1.0/README.md +171 -0
- market_wave-0.1.0/docs/assets/market-wave-hero.png +0 -0
- market_wave-0.1.0/docs/assets/market-wave-plot.png +0 -0
- market_wave-0.1.0/pyproject.toml +51 -0
- market_wave-0.1.0/src/market_wave/__init__.py +24 -0
- market_wave-0.1.0/src/market_wave/distribution.py +37 -0
- market_wave-0.1.0/src/market_wave/market.py +1018 -0
- market_wave-0.1.0/src/market_wave/state.py +92 -0
- market_wave-0.1.0/tests/test_market_wave_api_contract.py +587 -0
- market_wave-0.1.0/tests/test_market_wave_plotting.py +146 -0
- market_wave-0.1.0/uv.lock +887 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Python
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: astral-sh/setup-uv@v5
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- run: uv sync --extra dev
|
|
23
|
+
- run: uv run ruff check .
|
|
24
|
+
- run: uv run pytest
|
|
25
|
+
|
|
26
|
+
publish:
|
|
27
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
28
|
+
needs: test
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
permissions:
|
|
31
|
+
contents: read
|
|
32
|
+
id-token: write
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: astral-sh/setup-uv@v5
|
|
36
|
+
- uses: actions/setup-python@v5
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.12"
|
|
39
|
+
- run: uv build
|
|
40
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Small Turtle 2
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: market-wave
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Discrete mixture distribution market intent simulator
|
|
5
|
+
Project-URL: Homepage, https://github.com/smturtle2/market-wave
|
|
6
|
+
Project-URL: Repository, https://github.com/smturtle2/market-wave
|
|
7
|
+
Author: Small Turtle 2
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: discrete-distribution,market,orderbook,simulation
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: matplotlib>=3.8
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# market-wave
|
|
27
|
+
|
|
28
|
+
<p align="center">
|
|
29
|
+
<img src="docs/assets/market-wave-hero.png" alt="market-wave abstract market intent simulation hero" />
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
<strong>Aggregate market intent simulation with discrete mixture distributions.</strong>
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<a href="https://pypi.org/project/market-wave/"><img alt="PyPI" src="https://img.shields.io/pypi/v/market-wave"></a>
|
|
38
|
+
<a href="https://pypi.org/project/market-wave/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/market-wave"></a>
|
|
39
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
40
|
+
<a href=".github/workflows/workflow.yml"><img alt="Tests" src="https://img.shields.io/badge/tests-pytest-2563eb"></a>
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<p align="center">
|
|
44
|
+
English | <a href="README.ko.md">한국어</a>
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
`market-wave` is a Python library for simulating market-wide entry and exit intent
|
|
48
|
+
without creating individual participants. It models aggregate buy/sell pressure,
|
|
49
|
+
position exits, order-book depth, cancellations, taker flow, and execution-driven
|
|
50
|
+
price movement on a discrete price grid.
|
|
51
|
+
|
|
52
|
+
It is not a forecasting model. It is a lightweight simulation primitive for
|
|
53
|
+
experiments, visualization, teaching, and strategy-environment prototyping.
|
|
54
|
+
|
|
55
|
+
## Why market-wave?
|
|
56
|
+
|
|
57
|
+
- **Aggregate intent, not agents**: market participants are represented by
|
|
58
|
+
probability mass over price, not by individual objects.
|
|
59
|
+
- **Discrete mixture distributions**: entry and exit pressure are PMFs on the
|
|
60
|
+
current price grid.
|
|
61
|
+
- **Execution-driven prices**: prices stay flat unless trades execute.
|
|
62
|
+
- **Inspectable state**: every step returns a `StepInfo` snapshot with PMFs,
|
|
63
|
+
volumes, order book state, position mass, VWAP, spread, and imbalance.
|
|
64
|
+
- **Built-in plotting**: `matplotlib` is included, with a clean light chart style
|
|
65
|
+
by default.
|
|
66
|
+
|
|
67
|
+
## Install
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install market-wave
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For local development:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git clone https://github.com/smturtle2/market-wave.git
|
|
77
|
+
cd market-wave
|
|
78
|
+
uv sync --extra dev
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Python `>=3.10` is supported.
|
|
82
|
+
|
|
83
|
+
## Quickstart
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from market_wave import Market
|
|
87
|
+
|
|
88
|
+
market = Market(initial_price=10_000, gap=10, popularity=1.0, seed=42)
|
|
89
|
+
steps = market.step(100)
|
|
90
|
+
|
|
91
|
+
last = steps[-1]
|
|
92
|
+
print(last.price_before, "->", last.price_after)
|
|
93
|
+
print(last.total_executed_volume)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`Market.step(n)` always returns `list[StepInfo]` and appends the same objects to
|
|
97
|
+
`market.history`.
|
|
98
|
+
|
|
99
|
+
## Visualization
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from market_wave import Market
|
|
103
|
+
|
|
104
|
+
market = Market(initial_price=10_000, gap=10, popularity=1.0, seed=42)
|
|
105
|
+
market.step(260)
|
|
106
|
+
|
|
107
|
+
fig, ax = market.plot(last=180)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
<p align="center">
|
|
111
|
+
<img src="docs/assets/market-wave-plot.png" alt="market-wave light pyplot chart showing price, volume, and imbalance" />
|
|
112
|
+
</p>
|
|
113
|
+
|
|
114
|
+
The default `market_wave` style uses a light three-panel chart: price/VWAP,
|
|
115
|
+
executed volume, and order-flow imbalance. Dark overlay mode is still available:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
fig, ax = market.plot(layout="overlay", style="market_wave_dark")
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Core Concepts
|
|
122
|
+
|
|
123
|
+
At every step, the market builds a price grid around the current price:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
price_grid = current_price +/- k * gap
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The simulator maintains four probability mass functions on that grid:
|
|
130
|
+
|
|
131
|
+
- `buy_entry_pmf`
|
|
132
|
+
- `sell_entry_pmf`
|
|
133
|
+
- `long_exit_pmf`
|
|
134
|
+
- `short_exit_pmf`
|
|
135
|
+
|
|
136
|
+
Each PMF is a normalized discrete mixture:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
pmf[x] = sum(component_weight * kernel(x, center_price, spread))
|
|
140
|
+
kernel(x, center, spread) proportional to exp(-abs(x - center) / spread)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The PMFs generate aggregate intent. The order book and execution layer then turn
|
|
144
|
+
that intent into limit flow, taker flow, cancellations, exits, matched volume, and
|
|
145
|
+
price changes.
|
|
146
|
+
|
|
147
|
+
## Execution Guarantee
|
|
148
|
+
|
|
149
|
+
Price movement is execution-driven:
|
|
150
|
+
|
|
151
|
+
- If a step has no executed volume, `price_after == price_before`.
|
|
152
|
+
- If trades execute, `price_after` is derived from that step's execution
|
|
153
|
+
statistics.
|
|
154
|
+
- `seed` makes the simulation reproducible for the same version and inputs.
|
|
155
|
+
|
|
156
|
+
This is a simulator, not a market data replay engine and not financial advice.
|
|
157
|
+
|
|
158
|
+
## API Overview
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from market_wave import (
|
|
162
|
+
Market,
|
|
163
|
+
MarketState,
|
|
164
|
+
IntensityState,
|
|
165
|
+
LatentState,
|
|
166
|
+
MixtureComponent,
|
|
167
|
+
DiscreteMixtureDistribution,
|
|
168
|
+
DistributionState,
|
|
169
|
+
OrderBookState,
|
|
170
|
+
PositionMassState,
|
|
171
|
+
StepInfo,
|
|
172
|
+
)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Useful `StepInfo` fields include:
|
|
176
|
+
|
|
177
|
+
- `price_before`, `price_after`, `price_change`
|
|
178
|
+
- `buy_entry_pmf`, `sell_entry_pmf`, `long_exit_pmf`, `short_exit_pmf`
|
|
179
|
+
- `buy_volume_by_price`, `sell_volume_by_price`
|
|
180
|
+
- `executed_volume_by_price`, `total_executed_volume`, `trade_count`
|
|
181
|
+
- `vwap_price`, `best_bid_before`, `best_ask_before`, `spread_after`
|
|
182
|
+
- `orderbook_before`, `orderbook_after`
|
|
183
|
+
- `position_mass_before`, `position_mass_after`
|
|
184
|
+
|
|
185
|
+
## Development
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
uv sync --extra dev
|
|
189
|
+
uv run ruff check .
|
|
190
|
+
uv run pytest
|
|
191
|
+
uv build
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
MIT
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# market-wave
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="docs/assets/market-wave-hero.png" alt="market-wave 시장 의도 시뮬레이션 히어로 이미지" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>이산 혼합분포로 시장 전체의 진입/탈출 의도를 시뮬레이션합니다.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://pypi.org/project/market-wave/"><img alt="PyPI" src="https://img.shields.io/pypi/v/market-wave"></a>
|
|
13
|
+
<a href="https://pypi.org/project/market-wave/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/market-wave"></a>
|
|
14
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
15
|
+
<a href=".github/workflows/workflow.yml"><img alt="Tests" src="https://img.shields.io/badge/tests-pytest-2563eb"></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="README.md">English</a> | 한국어
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
`market-wave`는 개별 참여자를 만들지 않고 시장 전체의 진입 가격과 탈출 가격
|
|
23
|
+
의도를 시뮬레이션하는 Python 라이브러리입니다. 집계된 매수/매도 압력, 포지션
|
|
24
|
+
청산, 호가창 깊이, 주문 취소, taker flow, 체결 기반 가격 변화를 이산 가격
|
|
25
|
+
그리드 위에서 다룹니다.
|
|
26
|
+
|
|
27
|
+
이 라이브러리는 가격 예측 모델이 아닙니다. 실험, 시각화, 교육, 전략 환경
|
|
28
|
+
프로토타이핑을 위한 가벼운 시뮬레이션 도구입니다.
|
|
29
|
+
|
|
30
|
+
## 왜 market-wave인가?
|
|
31
|
+
|
|
32
|
+
- **개별 agent가 아닌 집계 의도**: 참여자 객체를 만들지 않고 가격별 확률질량으로
|
|
33
|
+
시장 의도를 표현합니다.
|
|
34
|
+
- **이산 혼합분포**: 진입/탈출 압력을 현재 `price_grid` 위의 PMF로 모델링합니다.
|
|
35
|
+
- **체결 기반 가격**: 체결이 없으면 가격은 움직이지 않습니다.
|
|
36
|
+
- **관찰 가능한 상태**: 매 step마다 PMF, 거래량, 호가창, 포지션 mass, VWAP,
|
|
37
|
+
spread, imbalance가 담긴 `StepInfo`를 반환합니다.
|
|
38
|
+
- **내장 시각화**: `matplotlib` 기반의 깔끔한 light chart 스타일을 제공합니다.
|
|
39
|
+
|
|
40
|
+
## 설치
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install market-wave
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
로컬 개발:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git clone https://github.com/smturtle2/market-wave.git
|
|
50
|
+
cd market-wave
|
|
51
|
+
uv sync --extra dev
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Python `>=3.10`을 지원합니다.
|
|
55
|
+
|
|
56
|
+
## 빠른 시작
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from market_wave import Market
|
|
60
|
+
|
|
61
|
+
market = Market(initial_price=10_000, gap=10, popularity=1.0, seed=42)
|
|
62
|
+
steps = market.step(100)
|
|
63
|
+
|
|
64
|
+
last = steps[-1]
|
|
65
|
+
print(last.price_before, "->", last.price_after)
|
|
66
|
+
print(last.total_executed_volume)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`Market.step(n)`은 항상 `list[StepInfo]`를 반환하고, 같은 객체들을
|
|
70
|
+
`market.history`에 저장합니다.
|
|
71
|
+
|
|
72
|
+
## 시각화
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from market_wave import Market
|
|
76
|
+
|
|
77
|
+
market = Market(initial_price=10_000, gap=10, popularity=1.0, seed=42)
|
|
78
|
+
market.step(260)
|
|
79
|
+
|
|
80
|
+
fig, ax = market.plot(last=180)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
<p align="center">
|
|
84
|
+
<img src="docs/assets/market-wave-plot.png" alt="가격, 거래량, imbalance를 보여주는 market-wave light pyplot 차트" />
|
|
85
|
+
</p>
|
|
86
|
+
|
|
87
|
+
기본 `market_wave` 스타일은 가격/VWAP, 체결량, order-flow imbalance를 분리한
|
|
88
|
+
light 3-panel 차트입니다. Dark overlay 모드도 사용할 수 있습니다.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
fig, ax = market.plot(layout="overlay", style="market_wave_dark")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 핵심 개념
|
|
95
|
+
|
|
96
|
+
매 step마다 현재 가격 주변에 가격 그리드를 만듭니다.
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
price_grid = current_price +/- k * gap
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
시뮬레이터는 이 그리드 위에 네 개의 확률질량함수를 유지합니다.
|
|
103
|
+
|
|
104
|
+
- `buy_entry_pmf`
|
|
105
|
+
- `sell_entry_pmf`
|
|
106
|
+
- `long_exit_pmf`
|
|
107
|
+
- `short_exit_pmf`
|
|
108
|
+
|
|
109
|
+
각 PMF는 정규화된 이산 혼합분포입니다.
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
pmf[x] = sum(component_weight * kernel(x, center_price, spread))
|
|
113
|
+
kernel(x, center, spread) proportional to exp(-abs(x - center) / spread)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
PMF는 집계 의도를 만들고, 호가창/체결 레이어가 이를 limit flow, taker flow,
|
|
117
|
+
주문 취소, 청산, 체결량, 가격 변화로 바꿉니다.
|
|
118
|
+
|
|
119
|
+
## 체결 보장
|
|
120
|
+
|
|
121
|
+
가격 변화는 체결에 의해 발생합니다.
|
|
122
|
+
|
|
123
|
+
- 해당 step의 체결량이 없으면 `price_after == price_before`입니다.
|
|
124
|
+
- 체결이 있으면 `price_after`는 해당 step의 체결 통계에서 계산됩니다.
|
|
125
|
+
- 같은 버전과 같은 입력에서 `seed`는 재현 가능한 시뮬레이션을 만듭니다.
|
|
126
|
+
|
|
127
|
+
이 라이브러리는 시장 데이터 replay 엔진이 아니며, 금융 조언도 아닙니다.
|
|
128
|
+
|
|
129
|
+
## API 개요
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from market_wave import (
|
|
133
|
+
Market,
|
|
134
|
+
MarketState,
|
|
135
|
+
IntensityState,
|
|
136
|
+
LatentState,
|
|
137
|
+
MixtureComponent,
|
|
138
|
+
DiscreteMixtureDistribution,
|
|
139
|
+
DistributionState,
|
|
140
|
+
OrderBookState,
|
|
141
|
+
PositionMassState,
|
|
142
|
+
StepInfo,
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
자주 보는 `StepInfo` 필드:
|
|
147
|
+
|
|
148
|
+
- `price_before`, `price_after`, `price_change`
|
|
149
|
+
- `buy_entry_pmf`, `sell_entry_pmf`, `long_exit_pmf`, `short_exit_pmf`
|
|
150
|
+
- `buy_volume_by_price`, `sell_volume_by_price`
|
|
151
|
+
- `executed_volume_by_price`, `total_executed_volume`, `trade_count`
|
|
152
|
+
- `vwap_price`, `best_bid_before`, `best_ask_before`, `spread_after`
|
|
153
|
+
- `orderbook_before`, `orderbook_after`
|
|
154
|
+
- `position_mass_before`, `position_mass_after`
|
|
155
|
+
|
|
156
|
+
## 개발
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
uv sync --extra dev
|
|
160
|
+
uv run ruff check .
|
|
161
|
+
uv run pytest
|
|
162
|
+
uv build
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## 라이선스
|
|
166
|
+
|
|
167
|
+
MIT
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# market-wave
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="docs/assets/market-wave-hero.png" alt="market-wave abstract market intent simulation hero" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Aggregate market intent simulation with discrete mixture distributions.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://pypi.org/project/market-wave/"><img alt="PyPI" src="https://img.shields.io/pypi/v/market-wave"></a>
|
|
13
|
+
<a href="https://pypi.org/project/market-wave/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/market-wave"></a>
|
|
14
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
15
|
+
<a href=".github/workflows/workflow.yml"><img alt="Tests" src="https://img.shields.io/badge/tests-pytest-2563eb"></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
English | <a href="README.ko.md">한국어</a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
`market-wave` is a Python library for simulating market-wide entry and exit intent
|
|
23
|
+
without creating individual participants. It models aggregate buy/sell pressure,
|
|
24
|
+
position exits, order-book depth, cancellations, taker flow, and execution-driven
|
|
25
|
+
price movement on a discrete price grid.
|
|
26
|
+
|
|
27
|
+
It is not a forecasting model. It is a lightweight simulation primitive for
|
|
28
|
+
experiments, visualization, teaching, and strategy-environment prototyping.
|
|
29
|
+
|
|
30
|
+
## Why market-wave?
|
|
31
|
+
|
|
32
|
+
- **Aggregate intent, not agents**: market participants are represented by
|
|
33
|
+
probability mass over price, not by individual objects.
|
|
34
|
+
- **Discrete mixture distributions**: entry and exit pressure are PMFs on the
|
|
35
|
+
current price grid.
|
|
36
|
+
- **Execution-driven prices**: prices stay flat unless trades execute.
|
|
37
|
+
- **Inspectable state**: every step returns a `StepInfo` snapshot with PMFs,
|
|
38
|
+
volumes, order book state, position mass, VWAP, spread, and imbalance.
|
|
39
|
+
- **Built-in plotting**: `matplotlib` is included, with a clean light chart style
|
|
40
|
+
by default.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install market-wave
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
For local development:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
git clone https://github.com/smturtle2/market-wave.git
|
|
52
|
+
cd market-wave
|
|
53
|
+
uv sync --extra dev
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Python `>=3.10` is supported.
|
|
57
|
+
|
|
58
|
+
## Quickstart
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from market_wave import Market
|
|
62
|
+
|
|
63
|
+
market = Market(initial_price=10_000, gap=10, popularity=1.0, seed=42)
|
|
64
|
+
steps = market.step(100)
|
|
65
|
+
|
|
66
|
+
last = steps[-1]
|
|
67
|
+
print(last.price_before, "->", last.price_after)
|
|
68
|
+
print(last.total_executed_volume)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`Market.step(n)` always returns `list[StepInfo]` and appends the same objects to
|
|
72
|
+
`market.history`.
|
|
73
|
+
|
|
74
|
+
## Visualization
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from market_wave import Market
|
|
78
|
+
|
|
79
|
+
market = Market(initial_price=10_000, gap=10, popularity=1.0, seed=42)
|
|
80
|
+
market.step(260)
|
|
81
|
+
|
|
82
|
+
fig, ax = market.plot(last=180)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
<p align="center">
|
|
86
|
+
<img src="docs/assets/market-wave-plot.png" alt="market-wave light pyplot chart showing price, volume, and imbalance" />
|
|
87
|
+
</p>
|
|
88
|
+
|
|
89
|
+
The default `market_wave` style uses a light three-panel chart: price/VWAP,
|
|
90
|
+
executed volume, and order-flow imbalance. Dark overlay mode is still available:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
fig, ax = market.plot(layout="overlay", style="market_wave_dark")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Core Concepts
|
|
97
|
+
|
|
98
|
+
At every step, the market builds a price grid around the current price:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
price_grid = current_price +/- k * gap
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The simulator maintains four probability mass functions on that grid:
|
|
105
|
+
|
|
106
|
+
- `buy_entry_pmf`
|
|
107
|
+
- `sell_entry_pmf`
|
|
108
|
+
- `long_exit_pmf`
|
|
109
|
+
- `short_exit_pmf`
|
|
110
|
+
|
|
111
|
+
Each PMF is a normalized discrete mixture:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
pmf[x] = sum(component_weight * kernel(x, center_price, spread))
|
|
115
|
+
kernel(x, center, spread) proportional to exp(-abs(x - center) / spread)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The PMFs generate aggregate intent. The order book and execution layer then turn
|
|
119
|
+
that intent into limit flow, taker flow, cancellations, exits, matched volume, and
|
|
120
|
+
price changes.
|
|
121
|
+
|
|
122
|
+
## Execution Guarantee
|
|
123
|
+
|
|
124
|
+
Price movement is execution-driven:
|
|
125
|
+
|
|
126
|
+
- If a step has no executed volume, `price_after == price_before`.
|
|
127
|
+
- If trades execute, `price_after` is derived from that step's execution
|
|
128
|
+
statistics.
|
|
129
|
+
- `seed` makes the simulation reproducible for the same version and inputs.
|
|
130
|
+
|
|
131
|
+
This is a simulator, not a market data replay engine and not financial advice.
|
|
132
|
+
|
|
133
|
+
## API Overview
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from market_wave import (
|
|
137
|
+
Market,
|
|
138
|
+
MarketState,
|
|
139
|
+
IntensityState,
|
|
140
|
+
LatentState,
|
|
141
|
+
MixtureComponent,
|
|
142
|
+
DiscreteMixtureDistribution,
|
|
143
|
+
DistributionState,
|
|
144
|
+
OrderBookState,
|
|
145
|
+
PositionMassState,
|
|
146
|
+
StepInfo,
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Useful `StepInfo` fields include:
|
|
151
|
+
|
|
152
|
+
- `price_before`, `price_after`, `price_change`
|
|
153
|
+
- `buy_entry_pmf`, `sell_entry_pmf`, `long_exit_pmf`, `short_exit_pmf`
|
|
154
|
+
- `buy_volume_by_price`, `sell_volume_by_price`
|
|
155
|
+
- `executed_volume_by_price`, `total_executed_volume`, `trade_count`
|
|
156
|
+
- `vwap_price`, `best_bid_before`, `best_ask_before`, `spread_after`
|
|
157
|
+
- `orderbook_before`, `orderbook_after`
|
|
158
|
+
- `position_mass_before`, `position_mass_after`
|
|
159
|
+
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
uv sync --extra dev
|
|
164
|
+
uv run ruff check .
|
|
165
|
+
uv run pytest
|
|
166
|
+
uv build
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "market-wave"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Discrete mixture distribution market intent simulator"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Small Turtle 2" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["market", "simulation", "discrete-distribution", "orderbook"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"matplotlib>=3.8",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
dev = [
|
|
32
|
+
"pytest>=8",
|
|
33
|
+
"ruff>=0.5",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/smturtle2/market-wave"
|
|
38
|
+
Repository = "https://github.com/smturtle2/market-wave"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["src/market_wave"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
testpaths = ["tests"]
|
|
45
|
+
|
|
46
|
+
[tool.ruff]
|
|
47
|
+
line-length = 100
|
|
48
|
+
target-version = "py310"
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint]
|
|
51
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from .distribution import DiscreteMixtureDistribution, MixtureComponent
|
|
2
|
+
from .market import Market
|
|
3
|
+
from .state import (
|
|
4
|
+
DistributionState,
|
|
5
|
+
IntensityState,
|
|
6
|
+
LatentState,
|
|
7
|
+
MarketState,
|
|
8
|
+
OrderBookState,
|
|
9
|
+
PositionMassState,
|
|
10
|
+
StepInfo,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"DiscreteMixtureDistribution",
|
|
15
|
+
"DistributionState",
|
|
16
|
+
"IntensityState",
|
|
17
|
+
"LatentState",
|
|
18
|
+
"Market",
|
|
19
|
+
"MarketState",
|
|
20
|
+
"MixtureComponent",
|
|
21
|
+
"OrderBookState",
|
|
22
|
+
"PositionMassState",
|
|
23
|
+
"StepInfo",
|
|
24
|
+
]
|