twap-engine 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.
- twap_engine-0.1.0/LICENSE +21 -0
- twap_engine-0.1.0/PKG-INFO +128 -0
- twap_engine-0.1.0/README.md +104 -0
- twap_engine-0.1.0/pyproject.toml +36 -0
- twap_engine-0.1.0/setup.cfg +4 -0
- twap_engine-0.1.0/src/twap_engine/__init__.py +3 -0
- twap_engine-0.1.0/src/twap_engine/engine.py +196 -0
- twap_engine-0.1.0/src/twap_engine.egg-info/PKG-INFO +128 -0
- twap_engine-0.1.0/src/twap_engine.egg-info/SOURCES.txt +10 -0
- twap_engine-0.1.0/src/twap_engine.egg-info/dependency_links.txt +1 -0
- twap_engine-0.1.0/src/twap_engine.egg-info/requires.txt +1 -0
- twap_engine-0.1.0/src/twap_engine.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Akin Urkmez
|
|
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,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: twap-engine
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Borsa-agnostik, bağımsız bir TWAP (Time-Weighted Average Price) emir dağıtım motoru. ccxt destekli her borsada çalışır.
|
|
5
|
+
Author: Akin Urkmez
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://pypi.org/project/twap-engine/
|
|
8
|
+
Keywords: twap,trading,crypto,ccxt,algo-trading,execution
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: ccxt
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# TWAP Engine (Standalone)
|
|
26
|
+
|
|
27
|
+
Borsa-agnostik, bağımsız bir **Time-Weighted Average Price (TWAP)** emir
|
|
28
|
+
dağıtım motoru. Herhangi bir [ccxt](https://github.com/ccxt/ccxt) destekli
|
|
29
|
+
borsada (Binance, Bybit, Kraken, vb.) çalışır. Hiçbir belirli projeye ya da
|
|
30
|
+
altyapıya bağımlı değildir.
|
|
31
|
+
|
|
32
|
+
## Özellikler
|
|
33
|
+
|
|
34
|
+
- Büyük bir emri N eşit parçaya bölüp zaman aralığına yayar
|
|
35
|
+
- **Slippage-abort**: fiyat referans noktasından belirli bir yüzdeden fazla
|
|
36
|
+
kayarsa kalan dilimleri otomatik iptal eder
|
|
37
|
+
- **Minimum notional koruması**: borsanın minimum emir tutarının altında
|
|
38
|
+
kalacak dilimleri, hiç başlamadan reddeder
|
|
39
|
+
|
|
40
|
+
> Bu, **temel (ücretsiz) sürümdür** — mekanik TWAP dağıtımı ve temel
|
|
41
|
+
> güvenlik kontrollerini içerir. Eklenebilir/özel risk zekası (RSI, order
|
|
42
|
+
> book analizi, haber akışı gibi harici sinyallere göre otomatik karar veren
|
|
43
|
+
> katman) ayrı bir gelişmiş sürümün konusudur.
|
|
44
|
+
|
|
45
|
+
## Kurulum
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install twap-engine
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Kaynak koddan kurmak isterseniz:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone <bu-repo>
|
|
55
|
+
cd twap_engine_standalone
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Hızlı Başlangıç
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import asyncio
|
|
63
|
+
import ccxt.async_support as ccxt
|
|
64
|
+
from twap_engine import TWAPEngine
|
|
65
|
+
|
|
66
|
+
async def main():
|
|
67
|
+
exchange = ccxt.binance({
|
|
68
|
+
"apiKey": "...",
|
|
69
|
+
"secret": "...",
|
|
70
|
+
"enableRateLimit": True,
|
|
71
|
+
})
|
|
72
|
+
exchange.set_sandbox_mode(True) # ÖNCE TESTNET'TE DENEYİN
|
|
73
|
+
|
|
74
|
+
engine = TWAPEngine(
|
|
75
|
+
exchange=exchange,
|
|
76
|
+
symbol="BTC/USDT",
|
|
77
|
+
side="buy",
|
|
78
|
+
total_amount=0.01,
|
|
79
|
+
slices=5,
|
|
80
|
+
interval_s=2.0,
|
|
81
|
+
max_slippage_pct=0.003, # %0.3
|
|
82
|
+
min_notional_usd=10.0,
|
|
83
|
+
order_type="market",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
result = await engine.run()
|
|
87
|
+
print(result.status, result.slices_sent, "/", result.slices_requested)
|
|
88
|
+
|
|
89
|
+
await exchange.close()
|
|
90
|
+
|
|
91
|
+
asyncio.run(main())
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Daha fazla örnek için `example.py` dosyasına bakın.
|
|
95
|
+
|
|
96
|
+
## Sonuç Nesnesi (TWAPResult)
|
|
97
|
+
|
|
98
|
+
| Alan | Açıklama |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `status` | `COMPLETED`, `ABORTED_SLIPPAGE`, `REJECTED_MIN_NOTIONAL`, `PARTIAL_ERROR` |
|
|
101
|
+
| `slices_sent` / `slices_requested` | Kaç dilim gönderildi / istendi |
|
|
102
|
+
| `filled_amount` | Gönderilen toplam miktar (base asset) |
|
|
103
|
+
| `aborted_reason` | İptal/red nedeni (varsa) |
|
|
104
|
+
| `orders` | Borsadan dönen ham emir yanıtları |
|
|
105
|
+
| `errors` | Dilim bazında yakalanan hatalar |
|
|
106
|
+
|
|
107
|
+
## Testler
|
|
108
|
+
|
|
109
|
+
Gerçek borsaya bağlanmayan, sahte (fake) exchange ile çalışan hafif testler:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
python test_engine.py
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Sınırlamalar / Sorumluluk Reddi
|
|
116
|
+
|
|
117
|
+
- Bu yazılım **"OLDUĞU GİBİ" (AS-IS)** sunulmaktadır, HİÇBİR GARANTİ VERİLMEZ.
|
|
118
|
+
- Finansal kayıplardan yazar sorumlu değildir. Gerçek parayla kullanmadan
|
|
119
|
+
önce mutlaka testnet/sandbox ortamında test edin.
|
|
120
|
+
- Bu motor emir GÖNDERMEYİ yönetir; risk yönetimi, pozisyon takibi, kasa
|
|
121
|
+
muhasebesi gibi konular KAPSAM DIŞIDIR — kendi sisteminize entegre ederken
|
|
122
|
+
bunları siz eklemelisiniz.
|
|
123
|
+
- Yalnızca "spot" tarzı basit emirler için tasarlanmıştır; kaldıraçlı/vadeli
|
|
124
|
+
işlemler için ek risk kontrolleri (likidasyon, marj) GEREKLİDİR ve bu
|
|
125
|
+
pakette YOKTUR.
|
|
126
|
+
- Ticari kullanım/satış öncesi kendi lisans metninizi (MIT, ticari lisans
|
|
127
|
+
vb.) ve yasal sorumluluk reddi maddelerinizi eklemeniz önerilir — bu
|
|
128
|
+
paket bir lisans dosyası içermez.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# TWAP Engine (Standalone)
|
|
2
|
+
|
|
3
|
+
Borsa-agnostik, bağımsız bir **Time-Weighted Average Price (TWAP)** emir
|
|
4
|
+
dağıtım motoru. Herhangi bir [ccxt](https://github.com/ccxt/ccxt) destekli
|
|
5
|
+
borsada (Binance, Bybit, Kraken, vb.) çalışır. Hiçbir belirli projeye ya da
|
|
6
|
+
altyapıya bağımlı değildir.
|
|
7
|
+
|
|
8
|
+
## Özellikler
|
|
9
|
+
|
|
10
|
+
- Büyük bir emri N eşit parçaya bölüp zaman aralığına yayar
|
|
11
|
+
- **Slippage-abort**: fiyat referans noktasından belirli bir yüzdeden fazla
|
|
12
|
+
kayarsa kalan dilimleri otomatik iptal eder
|
|
13
|
+
- **Minimum notional koruması**: borsanın minimum emir tutarının altında
|
|
14
|
+
kalacak dilimleri, hiç başlamadan reddeder
|
|
15
|
+
|
|
16
|
+
> Bu, **temel (ücretsiz) sürümdür** — mekanik TWAP dağıtımı ve temel
|
|
17
|
+
> güvenlik kontrollerini içerir. Eklenebilir/özel risk zekası (RSI, order
|
|
18
|
+
> book analizi, haber akışı gibi harici sinyallere göre otomatik karar veren
|
|
19
|
+
> katman) ayrı bir gelişmiş sürümün konusudur.
|
|
20
|
+
|
|
21
|
+
## Kurulum
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install twap-engine
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Kaynak koddan kurmak isterseniz:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone <bu-repo>
|
|
31
|
+
cd twap_engine_standalone
|
|
32
|
+
pip install -e .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Hızlı Başlangıç
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import asyncio
|
|
39
|
+
import ccxt.async_support as ccxt
|
|
40
|
+
from twap_engine import TWAPEngine
|
|
41
|
+
|
|
42
|
+
async def main():
|
|
43
|
+
exchange = ccxt.binance({
|
|
44
|
+
"apiKey": "...",
|
|
45
|
+
"secret": "...",
|
|
46
|
+
"enableRateLimit": True,
|
|
47
|
+
})
|
|
48
|
+
exchange.set_sandbox_mode(True) # ÖNCE TESTNET'TE DENEYİN
|
|
49
|
+
|
|
50
|
+
engine = TWAPEngine(
|
|
51
|
+
exchange=exchange,
|
|
52
|
+
symbol="BTC/USDT",
|
|
53
|
+
side="buy",
|
|
54
|
+
total_amount=0.01,
|
|
55
|
+
slices=5,
|
|
56
|
+
interval_s=2.0,
|
|
57
|
+
max_slippage_pct=0.003, # %0.3
|
|
58
|
+
min_notional_usd=10.0,
|
|
59
|
+
order_type="market",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
result = await engine.run()
|
|
63
|
+
print(result.status, result.slices_sent, "/", result.slices_requested)
|
|
64
|
+
|
|
65
|
+
await exchange.close()
|
|
66
|
+
|
|
67
|
+
asyncio.run(main())
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Daha fazla örnek için `example.py` dosyasına bakın.
|
|
71
|
+
|
|
72
|
+
## Sonuç Nesnesi (TWAPResult)
|
|
73
|
+
|
|
74
|
+
| Alan | Açıklama |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `status` | `COMPLETED`, `ABORTED_SLIPPAGE`, `REJECTED_MIN_NOTIONAL`, `PARTIAL_ERROR` |
|
|
77
|
+
| `slices_sent` / `slices_requested` | Kaç dilim gönderildi / istendi |
|
|
78
|
+
| `filled_amount` | Gönderilen toplam miktar (base asset) |
|
|
79
|
+
| `aborted_reason` | İptal/red nedeni (varsa) |
|
|
80
|
+
| `orders` | Borsadan dönen ham emir yanıtları |
|
|
81
|
+
| `errors` | Dilim bazında yakalanan hatalar |
|
|
82
|
+
|
|
83
|
+
## Testler
|
|
84
|
+
|
|
85
|
+
Gerçek borsaya bağlanmayan, sahte (fake) exchange ile çalışan hafif testler:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python test_engine.py
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Sınırlamalar / Sorumluluk Reddi
|
|
92
|
+
|
|
93
|
+
- Bu yazılım **"OLDUĞU GİBİ" (AS-IS)** sunulmaktadır, HİÇBİR GARANTİ VERİLMEZ.
|
|
94
|
+
- Finansal kayıplardan yazar sorumlu değildir. Gerçek parayla kullanmadan
|
|
95
|
+
önce mutlaka testnet/sandbox ortamında test edin.
|
|
96
|
+
- Bu motor emir GÖNDERMEYİ yönetir; risk yönetimi, pozisyon takibi, kasa
|
|
97
|
+
muhasebesi gibi konular KAPSAM DIŞIDIR — kendi sisteminize entegre ederken
|
|
98
|
+
bunları siz eklemelisiniz.
|
|
99
|
+
- Yalnızca "spot" tarzı basit emirler için tasarlanmıştır; kaldıraçlı/vadeli
|
|
100
|
+
işlemler için ek risk kontrolleri (likidasyon, marj) GEREKLİDİR ve bu
|
|
101
|
+
pakette YOKTUR.
|
|
102
|
+
- Ticari kullanım/satış öncesi kendi lisans metninizi (MIT, ticari lisans
|
|
103
|
+
vb.) ve yasal sorumluluk reddi maddelerinizi eklemeniz önerilir — bu
|
|
104
|
+
paket bir lisans dosyası içermez.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "twap-engine"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Borsa-agnostik, bağımsız bir TWAP (Time-Weighted Average Price) emir dağıtım motoru. ccxt destekli her borsada çalışır."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Akin Urkmez" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["twap", "trading", "crypto", "ccxt", "algo-trading", "execution"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"ccxt",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://pypi.org/project/twap-engine/"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TWAP Engine — Bağımsız, Borsa-Agnostik TWAP Emir Dağıtım Motoru
|
|
3
|
+
================================================================
|
|
4
|
+
|
|
5
|
+
ccxt destekli HERHANGİ bir borsada çalışan, tek başına kullanılabilen bir
|
|
6
|
+
Time-Weighted Average Price (TWAP) emir dağıtım motoru. Belirli bir projeye
|
|
7
|
+
bağımlı değildir — kendi exchange client'ınızı verirsiniz. Kullanım için
|
|
8
|
+
README.md'ye bakın.
|
|
9
|
+
|
|
10
|
+
Not: Bu, TEMEL sürümdür — sadece mekanik TWAP dilimleme, slippage-abort ve
|
|
11
|
+
minimum notional koruması içerir. Özel/eklenebilir risk zekası (RSI, order
|
|
12
|
+
book analizi, haber akışı gibi harici sinyallere göre karar veren mantık)
|
|
13
|
+
ayrı, gelişmiş bir sürümün konusudur ve bu pakette YOKTUR.
|
|
14
|
+
"""
|
|
15
|
+
import asyncio
|
|
16
|
+
import logging
|
|
17
|
+
from dataclasses import dataclass, field
|
|
18
|
+
from enum import Enum
|
|
19
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger("twap_engine")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TWAPStatus(str, Enum):
|
|
25
|
+
COMPLETED = "COMPLETED" # Tüm dilimler başarıyla gönderildi
|
|
26
|
+
ABORTED_SLIPPAGE = "ABORTED_SLIPPAGE" # Fiyat sapması limiti aştı
|
|
27
|
+
REJECTED_MIN_NOTIONAL = "REJECTED_MIN_NOTIONAL" # Dilim başı tutar minimumun altında
|
|
28
|
+
PARTIAL_ERROR = "PARTIAL_ERROR" # Bazı dilimler hata verdi ama devam edildi
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class TWAPResult:
|
|
33
|
+
status: TWAPStatus
|
|
34
|
+
symbol: str
|
|
35
|
+
side: str
|
|
36
|
+
total_amount: float
|
|
37
|
+
slices_requested: int
|
|
38
|
+
slices_sent: int
|
|
39
|
+
reference_price: float
|
|
40
|
+
filled_amount: float = 0.0
|
|
41
|
+
aborted_reason: Optional[str] = None
|
|
42
|
+
orders: List[Dict[str, Any]] = field(default_factory=list)
|
|
43
|
+
errors: List[str] = field(default_factory=list)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class TWAPEngine:
|
|
47
|
+
"""
|
|
48
|
+
Borsa-agnostik TWAP emir dağıtım motoru.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
exchange: ccxt.async_support uyumlu, zaten kimlik doğrulanmış bir
|
|
52
|
+
exchange instance'ı (örn. ccxt.async_support.binance({...})).
|
|
53
|
+
Bu motor exchange'i OLUŞTURMAZ, sadece kullanır.
|
|
54
|
+
symbol: İşlem çifti, örn. "BTC/USDT" (ccxt formatı).
|
|
55
|
+
side: "buy" ya da "sell".
|
|
56
|
+
total_amount: Toplam miktar (base asset cinsinden, örn. BTC adedi).
|
|
57
|
+
slices: Kaç parçaya bölüneceği (varsayılan 5).
|
|
58
|
+
interval_s: Dilimler arası bekleme süresi, saniye (varsayılan 2.0).
|
|
59
|
+
max_slippage_pct: Referans fiyattan bu yüzdeden fazla sapma olursa
|
|
60
|
+
kalan dilimler iptal edilir (varsayılan 0.003 = %0.3).
|
|
61
|
+
min_notional_usd: Tek bir dilimin USD değeri bunun altındaysa TWAP
|
|
62
|
+
hiç başlamadan reddedilir (varsayılan 10.0 — Binance benzeri
|
|
63
|
+
borsaların tipik minimumu; kendi borsanızın kuralıyla değiştirin).
|
|
64
|
+
order_type: "market" ya da "limit" (limit için anlık fiyat kullanılır).
|
|
65
|
+
quote_price_fn: Opsiyonel. Fiyat almak için özel bir async fonksiyon
|
|
66
|
+
(varsayılan: exchange.fetch_ticker(symbol)['last']). Farklı bir
|
|
67
|
+
fiyat kaynağı (örn. kendi order book analiziniz) kullanmak
|
|
68
|
+
isterseniz buraya verin. İmza: async () -> float
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(
|
|
72
|
+
self,
|
|
73
|
+
exchange: Any,
|
|
74
|
+
symbol: str,
|
|
75
|
+
side: str,
|
|
76
|
+
total_amount: float,
|
|
77
|
+
slices: int = 5,
|
|
78
|
+
interval_s: float = 2.0,
|
|
79
|
+
max_slippage_pct: float = 0.003,
|
|
80
|
+
min_notional_usd: float = 10.0,
|
|
81
|
+
order_type: str = "market",
|
|
82
|
+
quote_price_fn: Optional[Callable[[], Any]] = None,
|
|
83
|
+
):
|
|
84
|
+
if side not in ("buy", "sell"):
|
|
85
|
+
raise ValueError("side 'buy' ya da 'sell' olmalıdır")
|
|
86
|
+
if slices < 1:
|
|
87
|
+
raise ValueError("slices en az 1 olmalıdır")
|
|
88
|
+
if total_amount <= 0:
|
|
89
|
+
raise ValueError("total_amount pozitif olmalıdır")
|
|
90
|
+
if order_type not in ("market", "limit"):
|
|
91
|
+
raise ValueError("order_type 'market' ya da 'limit' olmalıdır")
|
|
92
|
+
|
|
93
|
+
self.exchange = exchange
|
|
94
|
+
self.symbol = symbol
|
|
95
|
+
self.side = side
|
|
96
|
+
self.total_amount = total_amount
|
|
97
|
+
self.slices = slices
|
|
98
|
+
self.interval_s = interval_s
|
|
99
|
+
self.max_slippage_pct = max_slippage_pct
|
|
100
|
+
self.min_notional_usd = min_notional_usd
|
|
101
|
+
self.order_type = order_type
|
|
102
|
+
self._quote_price_fn = quote_price_fn or self._default_quote_price
|
|
103
|
+
|
|
104
|
+
async def _default_quote_price(self) -> float:
|
|
105
|
+
ticker = await self.exchange.fetch_ticker(self.symbol)
|
|
106
|
+
return float(ticker["last"])
|
|
107
|
+
|
|
108
|
+
async def run(self) -> TWAPResult:
|
|
109
|
+
"""TWAP'ı çalıştırır ve tamamlanınca sonucu döner.
|
|
110
|
+
|
|
111
|
+
Fire-and-forget istiyorsanız: asyncio.create_task(engine.run())
|
|
112
|
+
"""
|
|
113
|
+
slice_amount = self.total_amount / self.slices
|
|
114
|
+
|
|
115
|
+
reference_price = await self._quote_price_fn()
|
|
116
|
+
if reference_price is None or reference_price <= 0:
|
|
117
|
+
return TWAPResult(
|
|
118
|
+
status=TWAPStatus.REJECTED_MIN_NOTIONAL,
|
|
119
|
+
symbol=self.symbol, side=self.side,
|
|
120
|
+
total_amount=self.total_amount, slices_requested=self.slices,
|
|
121
|
+
slices_sent=0, reference_price=reference_price or 0.0,
|
|
122
|
+
aborted_reason=f"Geçersiz referans fiyat: {reference_price}",
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
slice_notional = slice_amount * reference_price
|
|
126
|
+
if slice_notional < self.min_notional_usd:
|
|
127
|
+
msg = (
|
|
128
|
+
f"Dilim başı ${slice_notional:.2f}, minimum ${self.min_notional_usd:.2f}. "
|
|
129
|
+
f"Ya slices'i azaltın ya da total_amount'i artırın."
|
|
130
|
+
)
|
|
131
|
+
logger.warning(f"[TWAP] REDDEDİLDİ: {msg}")
|
|
132
|
+
return TWAPResult(
|
|
133
|
+
status=TWAPStatus.REJECTED_MIN_NOTIONAL,
|
|
134
|
+
symbol=self.symbol, side=self.side,
|
|
135
|
+
total_amount=self.total_amount, slices_requested=self.slices,
|
|
136
|
+
slices_sent=0, reference_price=reference_price,
|
|
137
|
+
aborted_reason=msg,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
result = TWAPResult(
|
|
141
|
+
status=TWAPStatus.COMPLETED,
|
|
142
|
+
symbol=self.symbol, side=self.side,
|
|
143
|
+
total_amount=self.total_amount, slices_requested=self.slices,
|
|
144
|
+
slices_sent=0, reference_price=reference_price,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
logger.info(
|
|
148
|
+
f"[TWAP] {self.side.upper()} {self.total_amount} {self.symbol} "
|
|
149
|
+
f"{self.slices} dilime bölündü. Referans fiyat: {reference_price}"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
for i in range(self.slices):
|
|
153
|
+
try:
|
|
154
|
+
current_price = await self._quote_price_fn()
|
|
155
|
+
except Exception as e:
|
|
156
|
+
result.errors.append(f"Dilim {i+1} fiyat sorgusu hatası: {e}")
|
|
157
|
+
current_price = reference_price # son bilinen fiyata güven
|
|
158
|
+
|
|
159
|
+
deviation = abs(current_price - reference_price) / reference_price
|
|
160
|
+
if deviation > self.max_slippage_pct:
|
|
161
|
+
result.status = TWAPStatus.ABORTED_SLIPPAGE
|
|
162
|
+
result.aborted_reason = (
|
|
163
|
+
f"%{deviation*100:.3f} sapma, limit %{self.max_slippage_pct*100:.3f} "
|
|
164
|
+
f"({i}/{self.slices} dilim gönderilmişti)"
|
|
165
|
+
)
|
|
166
|
+
logger.warning(f"[TWAP] İPTAL (slippage): {result.aborted_reason}")
|
|
167
|
+
break
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
order_kwargs = dict(
|
|
171
|
+
symbol=self.symbol,
|
|
172
|
+
type=self.order_type,
|
|
173
|
+
side=self.side,
|
|
174
|
+
amount=slice_amount,
|
|
175
|
+
params={},
|
|
176
|
+
)
|
|
177
|
+
if self.order_type == "limit":
|
|
178
|
+
order_kwargs["price"] = current_price
|
|
179
|
+
|
|
180
|
+
order = await self.exchange.create_order(**order_kwargs)
|
|
181
|
+
result.orders.append(order)
|
|
182
|
+
result.filled_amount += slice_amount
|
|
183
|
+
result.slices_sent += 1
|
|
184
|
+
logger.info(
|
|
185
|
+
f"[TWAP] Dilim {i+1}/{self.slices} gönderildi: "
|
|
186
|
+
f"{slice_amount} @ ~{current_price}"
|
|
187
|
+
)
|
|
188
|
+
except Exception as e:
|
|
189
|
+
result.errors.append(f"Dilim {i+1} emir hatası: {e}")
|
|
190
|
+
result.status = TWAPStatus.PARTIAL_ERROR
|
|
191
|
+
logger.error(f"[TWAP] Dilim {i+1} başarısız: {e}")
|
|
192
|
+
|
|
193
|
+
if i < self.slices - 1:
|
|
194
|
+
await asyncio.sleep(self.interval_s)
|
|
195
|
+
|
|
196
|
+
return result
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: twap-engine
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Borsa-agnostik, bağımsız bir TWAP (Time-Weighted Average Price) emir dağıtım motoru. ccxt destekli her borsada çalışır.
|
|
5
|
+
Author: Akin Urkmez
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://pypi.org/project/twap-engine/
|
|
8
|
+
Keywords: twap,trading,crypto,ccxt,algo-trading,execution
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: ccxt
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# TWAP Engine (Standalone)
|
|
26
|
+
|
|
27
|
+
Borsa-agnostik, bağımsız bir **Time-Weighted Average Price (TWAP)** emir
|
|
28
|
+
dağıtım motoru. Herhangi bir [ccxt](https://github.com/ccxt/ccxt) destekli
|
|
29
|
+
borsada (Binance, Bybit, Kraken, vb.) çalışır. Hiçbir belirli projeye ya da
|
|
30
|
+
altyapıya bağımlı değildir.
|
|
31
|
+
|
|
32
|
+
## Özellikler
|
|
33
|
+
|
|
34
|
+
- Büyük bir emri N eşit parçaya bölüp zaman aralığına yayar
|
|
35
|
+
- **Slippage-abort**: fiyat referans noktasından belirli bir yüzdeden fazla
|
|
36
|
+
kayarsa kalan dilimleri otomatik iptal eder
|
|
37
|
+
- **Minimum notional koruması**: borsanın minimum emir tutarının altında
|
|
38
|
+
kalacak dilimleri, hiç başlamadan reddeder
|
|
39
|
+
|
|
40
|
+
> Bu, **temel (ücretsiz) sürümdür** — mekanik TWAP dağıtımı ve temel
|
|
41
|
+
> güvenlik kontrollerini içerir. Eklenebilir/özel risk zekası (RSI, order
|
|
42
|
+
> book analizi, haber akışı gibi harici sinyallere göre otomatik karar veren
|
|
43
|
+
> katman) ayrı bir gelişmiş sürümün konusudur.
|
|
44
|
+
|
|
45
|
+
## Kurulum
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install twap-engine
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Kaynak koddan kurmak isterseniz:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone <bu-repo>
|
|
55
|
+
cd twap_engine_standalone
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Hızlı Başlangıç
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import asyncio
|
|
63
|
+
import ccxt.async_support as ccxt
|
|
64
|
+
from twap_engine import TWAPEngine
|
|
65
|
+
|
|
66
|
+
async def main():
|
|
67
|
+
exchange = ccxt.binance({
|
|
68
|
+
"apiKey": "...",
|
|
69
|
+
"secret": "...",
|
|
70
|
+
"enableRateLimit": True,
|
|
71
|
+
})
|
|
72
|
+
exchange.set_sandbox_mode(True) # ÖNCE TESTNET'TE DENEYİN
|
|
73
|
+
|
|
74
|
+
engine = TWAPEngine(
|
|
75
|
+
exchange=exchange,
|
|
76
|
+
symbol="BTC/USDT",
|
|
77
|
+
side="buy",
|
|
78
|
+
total_amount=0.01,
|
|
79
|
+
slices=5,
|
|
80
|
+
interval_s=2.0,
|
|
81
|
+
max_slippage_pct=0.003, # %0.3
|
|
82
|
+
min_notional_usd=10.0,
|
|
83
|
+
order_type="market",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
result = await engine.run()
|
|
87
|
+
print(result.status, result.slices_sent, "/", result.slices_requested)
|
|
88
|
+
|
|
89
|
+
await exchange.close()
|
|
90
|
+
|
|
91
|
+
asyncio.run(main())
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Daha fazla örnek için `example.py` dosyasına bakın.
|
|
95
|
+
|
|
96
|
+
## Sonuç Nesnesi (TWAPResult)
|
|
97
|
+
|
|
98
|
+
| Alan | Açıklama |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `status` | `COMPLETED`, `ABORTED_SLIPPAGE`, `REJECTED_MIN_NOTIONAL`, `PARTIAL_ERROR` |
|
|
101
|
+
| `slices_sent` / `slices_requested` | Kaç dilim gönderildi / istendi |
|
|
102
|
+
| `filled_amount` | Gönderilen toplam miktar (base asset) |
|
|
103
|
+
| `aborted_reason` | İptal/red nedeni (varsa) |
|
|
104
|
+
| `orders` | Borsadan dönen ham emir yanıtları |
|
|
105
|
+
| `errors` | Dilim bazında yakalanan hatalar |
|
|
106
|
+
|
|
107
|
+
## Testler
|
|
108
|
+
|
|
109
|
+
Gerçek borsaya bağlanmayan, sahte (fake) exchange ile çalışan hafif testler:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
python test_engine.py
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Sınırlamalar / Sorumluluk Reddi
|
|
116
|
+
|
|
117
|
+
- Bu yazılım **"OLDUĞU GİBİ" (AS-IS)** sunulmaktadır, HİÇBİR GARANTİ VERİLMEZ.
|
|
118
|
+
- Finansal kayıplardan yazar sorumlu değildir. Gerçek parayla kullanmadan
|
|
119
|
+
önce mutlaka testnet/sandbox ortamında test edin.
|
|
120
|
+
- Bu motor emir GÖNDERMEYİ yönetir; risk yönetimi, pozisyon takibi, kasa
|
|
121
|
+
muhasebesi gibi konular KAPSAM DIŞIDIR — kendi sisteminize entegre ederken
|
|
122
|
+
bunları siz eklemelisiniz.
|
|
123
|
+
- Yalnızca "spot" tarzı basit emirler için tasarlanmıştır; kaldıraçlı/vadeli
|
|
124
|
+
işlemler için ek risk kontrolleri (likidasyon, marj) GEREKLİDİR ve bu
|
|
125
|
+
pakette YOKTUR.
|
|
126
|
+
- Ticari kullanım/satış öncesi kendi lisans metninizi (MIT, ticari lisans
|
|
127
|
+
vb.) ve yasal sorumluluk reddi maddelerinizi eklemeniz önerilir — bu
|
|
128
|
+
paket bir lisans dosyası içermez.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/twap_engine/__init__.py
|
|
5
|
+
src/twap_engine/engine.py
|
|
6
|
+
src/twap_engine.egg-info/PKG-INFO
|
|
7
|
+
src/twap_engine.egg-info/SOURCES.txt
|
|
8
|
+
src/twap_engine.egg-info/dependency_links.txt
|
|
9
|
+
src/twap_engine.egg-info/requires.txt
|
|
10
|
+
src/twap_engine.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ccxt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
twap_engine
|