walrasquant 0.3.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.
- walrasquant-0.3.2/PKG-INFO +769 -0
- walrasquant-0.3.2/README.md +729 -0
- walrasquant-0.3.2/pyproject.toml +55 -0
- walrasquant-0.3.2/src/walrasquant/__init__.py +7 -0
- walrasquant-0.3.2/src/walrasquant/aggregation.py +440 -0
- walrasquant-0.3.2/src/walrasquant/backends/__init__.py +4 -0
- walrasquant-0.3.2/src/walrasquant/backends/db.py +131 -0
- walrasquant-0.3.2/src/walrasquant/backends/db_postgresql.py +356 -0
- walrasquant-0.3.2/src/walrasquant/backends/db_sqlite.py +346 -0
- walrasquant-0.3.2/src/walrasquant/base/__init__.py +26 -0
- walrasquant-0.3.2/src/walrasquant/base/api_client.py +56 -0
- walrasquant-0.3.2/src/walrasquant/base/connector.py +824 -0
- walrasquant-0.3.2/src/walrasquant/base/ems.py +660 -0
- walrasquant-0.3.2/src/walrasquant/base/exchange.py +209 -0
- walrasquant-0.3.2/src/walrasquant/base/oms.py +246 -0
- walrasquant-0.3.2/src/walrasquant/base/retry.py +220 -0
- walrasquant-0.3.2/src/walrasquant/base/sms.py +525 -0
- walrasquant-0.3.2/src/walrasquant/base/ws_client.py +406 -0
- walrasquant-0.3.2/src/walrasquant/cli/__init__.py +7 -0
- walrasquant-0.3.2/src/walrasquant/cli/app.py +191 -0
- walrasquant-0.3.2/src/walrasquant/cli/commands/__init__.py +1 -0
- walrasquant-0.3.2/src/walrasquant/cli/main.py +199 -0
- walrasquant-0.3.2/src/walrasquant/cli/monitor/__init__.py +1 -0
- walrasquant-0.3.2/src/walrasquant/cli/monitor/state_exporter.py +263 -0
- walrasquant-0.3.2/src/walrasquant/cli/widgets/__init__.py +1 -0
- walrasquant-0.3.2/src/walrasquant/cli/widgets/balances.py +104 -0
- walrasquant-0.3.2/src/walrasquant/cli/widgets/dashboard.py +106 -0
- walrasquant-0.3.2/src/walrasquant/cli/widgets/positions.py +111 -0
- walrasquant-0.3.2/src/walrasquant/config.py +229 -0
- walrasquant-0.3.2/src/walrasquant/constants.py +371 -0
- walrasquant-0.3.2/src/walrasquant/core/__init__.py +0 -0
- walrasquant-0.3.2/src/walrasquant/core/cache.py +701 -0
- walrasquant-0.3.2/src/walrasquant/core/connection.py +41 -0
- walrasquant-0.3.2/src/walrasquant/core/entity.py +482 -0
- walrasquant-0.3.2/src/walrasquant/core/nautilius_core.py +98 -0
- walrasquant-0.3.2/src/walrasquant/core/registry.py +39 -0
- walrasquant-0.3.2/src/walrasquant/engine.py +716 -0
- walrasquant-0.3.2/src/walrasquant/error.py +34 -0
- walrasquant-0.3.2/src/walrasquant/exchange/__init__.py +13 -0
- walrasquant-0.3.2/src/walrasquant/exchange/base_factory.py +170 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/__init__.py +31 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/connector.py +860 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/constants.py +1186 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/ems.py +136 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/error.py +48 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/exchange.py +123 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/factory.py +106 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/oms.py +1524 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/rest_api.py +1484 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/schema.py +978 -0
- walrasquant-0.3.2/src/walrasquant/exchange/binance/websockets.py +384 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/__init__.py +28 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/connector.py +575 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/constants.py +452 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/ems.py +215 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/error.py +36 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/exchange.py +111 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/factory.py +120 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/oms.py +1348 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/rest_api.py +614 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/schema.py +885 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bitget/websockets.py +761 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/__init__.py +32 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/connector.py +796 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/constants.py +528 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/ems.py +114 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/error.py +36 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/exchange.py +102 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/factory.py +120 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/oms.py +978 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/rest_api.py +584 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/schema.py +848 -0
- walrasquant-0.3.2/src/walrasquant/exchange/bybit/websockets.py +306 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/__init__.py +28 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/connector.py +367 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/constants.py +391 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/ems.py +198 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/error.py +48 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/exchange.py +108 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/factory.py +116 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/oms.py +864 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/rest_api.py +349 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/schema.py +583 -0
- walrasquant-0.3.2/src/walrasquant/exchange/hyperliquid/websockets.py +576 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/__init__.py +25 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/connector.py +859 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/constants.py +556 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/ems.py +142 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/error.py +63 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/exchange.py +94 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/factory.py +126 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/oms.py +1027 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/rest_api.py +843 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/schema.py +1393 -0
- walrasquant-0.3.2/src/walrasquant/exchange/okx/websockets.py +420 -0
- walrasquant-0.3.2/src/walrasquant/exchange/registry.py +201 -0
- walrasquant-0.3.2/src/walrasquant/execution/__init__.py +24 -0
- walrasquant-0.3.2/src/walrasquant/execution/algorithm.py +924 -0
- walrasquant-0.3.2/src/walrasquant/execution/algorithms/__init__.py +3 -0
- walrasquant-0.3.2/src/walrasquant/execution/algorithms/twap.py +392 -0
- walrasquant-0.3.2/src/walrasquant/execution/config.py +34 -0
- walrasquant-0.3.2/src/walrasquant/execution/constants.py +27 -0
- walrasquant-0.3.2/src/walrasquant/execution/schema.py +62 -0
- walrasquant-0.3.2/src/walrasquant/indicator.py +374 -0
- walrasquant-0.3.2/src/walrasquant/push.py +74 -0
- walrasquant-0.3.2/src/walrasquant/schema.py +695 -0
- walrasquant-0.3.2/src/walrasquant/strategy.py +1582 -0
- walrasquant-0.3.2/src/walrasquant/web/__init__.py +16 -0
- walrasquant-0.3.2/src/walrasquant/web/app.py +157 -0
- walrasquant-0.3.2/src/walrasquant/web/server.py +89 -0
|
@@ -0,0 +1,769 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: walrasquant
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Summary: fastest python trading bot
|
|
5
|
+
Author: River-Shi
|
|
6
|
+
Author-email: River-Shi <nachuan.shi.quant@gmail.com>
|
|
7
|
+
License: MIT LICENSE
|
|
8
|
+
Requires-Dist: numpy>=1.26.4,<2.2.1
|
|
9
|
+
Requires-Dist: redis>=5.2.1,<6.0.0
|
|
10
|
+
Requires-Dist: msgspec>=0.19.0,<0.20.0
|
|
11
|
+
Requires-Dist: cython>=3.0.11,<4.0.0
|
|
12
|
+
Requires-Dist: certifi>=2025.1.31,<2026.0.0
|
|
13
|
+
Requires-Dist: bcrypt>=4.2.1,<5.0.0
|
|
14
|
+
Requires-Dist: zmq>=0.0.0,<0.0.1
|
|
15
|
+
Requires-Dist: apscheduler>=3.11.0,<4.0.0
|
|
16
|
+
Requires-Dist: returns>=0.24.0,<0.25.0
|
|
17
|
+
Requires-Dist: pathlib>=1.0.1,<2.0.0
|
|
18
|
+
Requires-Dist: aiosqlite>=0.21.0,<0.22.0
|
|
19
|
+
Requires-Dist: uvloop>=0.21.0
|
|
20
|
+
Requires-Dist: throttled-py>=2.2.3
|
|
21
|
+
Requires-Dist: asyncpg>=0.30.0
|
|
22
|
+
Requires-Dist: psycopg2-binary>=2.9.10
|
|
23
|
+
Requires-Dist: textual>=0.85.0
|
|
24
|
+
Requires-Dist: click>=8.1.0
|
|
25
|
+
Requires-Dist: pycryptodome>=3.23.0
|
|
26
|
+
Requires-Dist: eth-account>=0.13.7
|
|
27
|
+
Requires-Dist: typing-extensions>=4.12.2
|
|
28
|
+
Requires-Dist: fastapi>=0.117.1
|
|
29
|
+
Requires-Dist: uvicorn>=0.36.0
|
|
30
|
+
Requires-Dist: picows>=1.10.2
|
|
31
|
+
Requires-Dist: dynaconf[redis]>=3.2.12
|
|
32
|
+
Requires-Dist: nexuslog>=0.4.4
|
|
33
|
+
Requires-Dist: pandas>=2.3.3,<3.0.0
|
|
34
|
+
Requires-Dist: walras-nexuscore>=0.1.3
|
|
35
|
+
Requires-Dist: flashduty-sdk>=0.1.1
|
|
36
|
+
Requires-Dist: httpx>=0.28.1
|
|
37
|
+
Requires-Dist: ccxt>=4.5.34
|
|
38
|
+
Requires-Python: >=3.11, <3.14
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
<picture>
|
|
42
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/source/_static/logo-dark.png">
|
|
43
|
+
<source media="(prefers-color-scheme: light)" srcset="docs/source/_static/logo-light.png">
|
|
44
|
+
<img alt="nexustrader Logo" src="docs/source/_static/logo-light.png">
|
|
45
|
+
</picture>
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
- **WebSite**: https://nexustrader.quantweb3.ai/
|
|
53
|
+
- **Docs**: https://nexustrader.readthedocs.io/en/latest/
|
|
54
|
+
- **Support**: [quantweb3.ai@gmail.com](mailto:quantweb3.ai@gmail.com)
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
###############################################################
|
|
58
|
+
## ##
|
|
59
|
+
## ##
|
|
60
|
+
## ███ ██ ███████ ██ ██ ██ ██ ███████ ##
|
|
61
|
+
## ████ ██ ██ ██ ██ ██ ██ ██ ##
|
|
62
|
+
## ██ ██ ██ █████ ███ ██ ██ ███████ ##
|
|
63
|
+
## ██ ██ ██ ██ ██ ██ ██ ██ ██ ##
|
|
64
|
+
## ██ ████ ███████ ██ ██ ██████ ███████ ##
|
|
65
|
+
## ##
|
|
66
|
+
## ##
|
|
67
|
+
## ████████ ██████ █████ ██████ ███████ ██████ ##
|
|
68
|
+
## ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ##
|
|
69
|
+
## ██ ██████ ███████ ██ ██ █████ ██████ ##
|
|
70
|
+
## ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ##
|
|
71
|
+
## ██ ██ ██ ██ ██ ██████ ███████ ██ ██ ##
|
|
72
|
+
## ##
|
|
73
|
+
## ##
|
|
74
|
+
###############################################################
|
|
75
|
+
```
|
|
76
|
+
## Introduction
|
|
77
|
+
|
|
78
|
+
NexusTrader is a professional-grade open-source quantitative trading platform, specifically designed for **large capital
|
|
79
|
+
management** and **complex strategy development**, dedicated to providing high-performance, scalable, and user-friendly
|
|
80
|
+
quantitative trading solutions.
|
|
81
|
+
|
|
82
|
+
## Overview
|
|
83
|
+
|
|
84
|
+
### Core Advantages
|
|
85
|
+
|
|
86
|
+
- 🚀 **Professionally Optimized Order Algorithms:** Deep optimization for algorithmic orders including TWAP, effectively
|
|
87
|
+
reducing market impact costs. Users can easily integrate their own execution signals to achieve more efficient and
|
|
88
|
+
precise order execution.
|
|
89
|
+
- 💰 **Professional Arbitrage Strategy Support:** Provides professional optimization for various arbitrage strategies,
|
|
90
|
+
including funding rate arbitrage and cross-exchange arbitrage, supporting real-time tracking and trading of thousands
|
|
91
|
+
of trading pairs to help users easily capture arbitrage opportunities.
|
|
92
|
+
- 🚧 **Full-Featured Quantitative Trading Framework:** Users don't need to build frameworks or handle complex exchange
|
|
93
|
+
interface details themselves. NexusTrader has integrated professional position management, order management, fund
|
|
94
|
+
management, and statistical analysis modules, allowing users to focus on writing strategy logic and quickly implement
|
|
95
|
+
quantitative trading.
|
|
96
|
+
- 🚀 **Multi-Market Support and High Scalability:** Supports large-scale multi-market tracking and high-frequency strategy
|
|
97
|
+
execution, covering a wide range of trading instruments, making it an ideal choice for professional trading needs.
|
|
98
|
+
|
|
99
|
+
### Why NexusTrader Is More Efficient?
|
|
100
|
+
|
|
101
|
+
- **Enhanced Event Loop Performance**: NexusTrader leverages [uvloop](https://github.com/MagicStack/uvloop), a high-performance event loop, delivering speeds up to 2-4 times faster than Python's default asyncio loop.
|
|
102
|
+
|
|
103
|
+
- **High-Performance WebSocket Framework**: Built with [picows](https://github.com/tarasko/picows), a Cython-based WebSocket library that matches the speed of C++'s Boost.Beast, significantly outperforming Python alternatives like websockets and aiohttp.
|
|
104
|
+
|
|
105
|
+
- **Optimized Data Serialization**: Utilizing `msgspec` for serialization and deserialization, NexusTrader achieves unmatched efficiency, surpassing tools like `orjson`, `ujson`, and `json`. All data classes are implemented with `msgspec.Struct` for maximum performance.
|
|
106
|
+
|
|
107
|
+
- **Scalable Order Management**: Orders are handled efficiently using `asyncio.Queue`, ensuring seamless processing even at high volumes.
|
|
108
|
+
|
|
109
|
+
- **Rust-Powered Core Components**: Core modules such as the MessageBus and Clock are implemented in Rust, combining Rust's speed and reliability with Python's flexibility through the [nautilius](https://github.com/nautilius/nautilius) framework.
|
|
110
|
+
|
|
111
|
+
### Comparison with Other Frameworks
|
|
112
|
+
|
|
113
|
+
| Framework | Websocket Package | Data Serialization | Strategy Support | Advantages | Disadvantages |
|
|
114
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------ | -------------------------------------------------- | ---------------- | -------------------------------------------------- | ------------------------------------------------- |
|
|
115
|
+
| **NexusTrader** | [picows](https://picows.readthedocs.io/en/stable/introduction.html#installation) | [msgspec](https://jcristharif.com/msgspec/) | ✅ | Professionally optimized for speed and low latency | Requires some familiarity with async workflows |
|
|
116
|
+
| [HummingBot](https://github.com/hummingbot/hummingbot?tab=readme-ov-file) | aiohttp | [ujson](https://pypi.org/project/ujson/) | ✅ | Widely adopted with robust community support | Slower WebSocket handling and limited flexibility |
|
|
117
|
+
| [Freqtrade](https://github.com/freqtrade/freqtrade) | websockets | [orjson](https://github.com/ijl/orjson) | ✅ | Flexible strategy support | Higher resource consumption |
|
|
118
|
+
| [crypto-feed](https://github.com/bmoscon/cryptofeed) | [websockets](https://websockets.readthedocs.io/en/stable/) | [yapic.json](https://pypi.org/project/yapic.json/) | ❌ | Simple design for feed-only use | Lacks trading support and advanced features |
|
|
119
|
+
| [ccxt](https://github.com/bmoscon/cryptofeed) | [aiohttp](https://docs.aiohttp.org/en/stable/client_reference.html) | json | ❌ | Great REST API support | Limited WebSocket performance |
|
|
120
|
+
| [binance-futures-connector](https://github.com/binance/binance-futures-connector-python) | [websocket-client](https://websocket-client.readthedocs.io/en/latest/examples.html) | json | ❌ | Optimized for Binance-specific integration | Limited to Binance Futures |
|
|
121
|
+
| [python-okx](https://github.com/okxapi/python-okx) | websockets | json | ❌ | Dedicated to OKX trading | Limited to OKX platform |
|
|
122
|
+
| [unicorn-binance-websocket-api](https://github.com/LUCIT-Systems-and-Development/unicorn-binance-websocket-api) | websockets | [ujson](https://pypi.org/project/ujson/) | ❌ | Easy-to-use for Binance users | Restricted to Binance and resource-heavy |
|
|
123
|
+
|
|
124
|
+
### Architecture (data flow)
|
|
125
|
+
The core of Tradebot is the `Connector`, which is responsible for connecting to the exchange and data flow. Through the `PublicConnector`, users can access market data from the exchange, and through the `PrivateConnector`, users can execute trades and receive callbacks for trade data. Orders are submitted through the ``OrderExecutionSystem``, which is responsible for submitting orders to the exchange and obtaining the order ID from the exchange. Order status management is handled by the `OrderManagementSystem`, which is responsible for managing the status of orders and sending them to the `Strategy`.
|
|
126
|
+
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
### Features
|
|
130
|
+
|
|
131
|
+
- 🌍 Multi-Exchange Integration: Effortlessly connect to top exchanges like Binance, Bybit, and OKX, with an extensible design to support additional platforms.
|
|
132
|
+
- ⚡ Asynchronous Operations: Built on asyncio for highly efficient, scalable performance, even during high-frequency trading.
|
|
133
|
+
- 📡 Real-Time Data Streaming: Reliable WebSocket support for live market data, order book updates, and trade execution notifications.
|
|
134
|
+
- 📊 Advanced Order Management: Execute diverse order types (limit, market, stop) with optimized, professional-grade order handling.
|
|
135
|
+
- 📋 Account Monitoring: Real-time tracking of balances, positions, and PnL across multiple exchanges with integrated monitoring tools.
|
|
136
|
+
- 🛠️ Modular Architecture: Flexible framework to add exchanges, instruments, or custom strategies with ease.
|
|
137
|
+
- 🔄 Strategy Execution & Backtesting: Seamlessly transition from strategy testing to live trading with built-in tools.
|
|
138
|
+
- 📈 Scalability: Designed to handle large-scale, multi-market operations for retail and institutional traders alike.
|
|
139
|
+
- 💰 Risk & Fund Management: Optimize capital allocation and control risk exposure with integrated management tools.
|
|
140
|
+
- 🔔 Instant Notifications: Stay updated with alerts for trades, market changes, and custom conditions.
|
|
141
|
+
|
|
142
|
+
### Supported Exchanges
|
|
143
|
+
|
|
144
|
+
| OKX | Binance | BYBIT | HYPERLIQUID | BITGET |
|
|
145
|
+
| --------| ------ | ------- | ------- | ------- |
|
|
146
|
+
| <img src="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/9a411426-3711-47d4-9c1a-dcf72973ddfc/dfj37e6-d8b49926-d115-4368-9de8-09a80077fb4f.png/v1/fill/w_1280,h_1280/okx_okb_logo_by_saphyl_dfj37e6-fullview.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTI4MCIsInBhdGgiOiJcL2ZcLzlhNDExNDI2LTM3MTEtNDdkNC05YzFhLWRjZjcyOTczZGRmY1wvZGZqMzdlNi1kOGI0OTkyNi1kMTE1LTQzNjgtOWRlOC0wOWE4MDA3N2ZiNGYucG5nIiwid2lkdGgiOiI8PTEyODAifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ.kH6v6nu55xLephOzAFFhD2uCYkmFdLsBoTkSuQvtBpo" width="100"> | <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Binance_Logo.svg/768px-Binance_Logo.svg.png" width="100"> | <img src="https://brandlogo.org/wp-content/uploads/2024/02/Bybit-Logo.png" width="100"> | <img src="https://avatars.githubusercontent.com/u/129421375?s=280&v=4" width="100"> | <img src="https://s2.coinmarketcap.com/static/img/coins/200x200/11092.png" width="100"> |
|
|
147
|
+
|
|
148
|
+
## Installation
|
|
149
|
+
|
|
150
|
+
### Prerequisites
|
|
151
|
+
|
|
152
|
+
- Python 3.11+
|
|
153
|
+
- Redis
|
|
154
|
+
- Poetry (recommended)
|
|
155
|
+
- build-essential
|
|
156
|
+
|
|
157
|
+
### Install Build Essentials
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
sudo apt-get update
|
|
161
|
+
sudo apt-get install build-essential
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### From PyPI
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
pip install nexustrader
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### From Source
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
git clone https://github.com/RiverTrading/NexusTrader
|
|
174
|
+
cd NexusTrader
|
|
175
|
+
poetry install
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
> **Note**
|
|
179
|
+
> more details can be found in the [installation guide](https://nexustrader.readthedocs.io/en/latest/installation.html)
|
|
180
|
+
|
|
181
|
+
### Quick Start
|
|
182
|
+
|
|
183
|
+
Here's a basic example of how to use nexustrader, demonstrating a simple buy and sell strategy on OKX.
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from decimal import Decimal
|
|
187
|
+
|
|
188
|
+
from nexustrader.constants import settings
|
|
189
|
+
from nexustrader.config import Config, PublicConnectorConfig, PrivateConnectorConfig, BasicConfig
|
|
190
|
+
from nexustrader.strategy import Strategy
|
|
191
|
+
from nexustrader.constants import ExchangeType, OrderSide, OrderType
|
|
192
|
+
from nexustrader.exchange.okx import OkxAccountType
|
|
193
|
+
from nexustrader.schema import BookL1, Order
|
|
194
|
+
from nexustrader.engine import Engine
|
|
195
|
+
|
|
196
|
+
# Retrieve API credentials from settings
|
|
197
|
+
OKX_API_KEY = settings.OKX.DEMO_1.api_key
|
|
198
|
+
OKX_SECRET = settings.OKX.DEMO_1.secret
|
|
199
|
+
OKX_PASSPHRASE = settings.OKX.DEMO_1.passphrase
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class Demo(Strategy):
|
|
203
|
+
def __init__(self):
|
|
204
|
+
super().__init__()
|
|
205
|
+
self.subscribe_bookl1(symbols=["BTCUSDT-PERP.OKX"]) # Subscribe to the order book for the specified symbol
|
|
206
|
+
self.signal = True # Initialize signal to control order execution
|
|
207
|
+
|
|
208
|
+
def on_failed_order(self, order: Order):
|
|
209
|
+
print(order) # Log failed orders
|
|
210
|
+
|
|
211
|
+
def on_pending_order(self, order: Order):
|
|
212
|
+
print(order) # Log pending orders
|
|
213
|
+
|
|
214
|
+
def on_accepted_order(self, order: Order):
|
|
215
|
+
print(order) # Log accepted orders
|
|
216
|
+
|
|
217
|
+
def on_partially_filled_order(self, order: Order):
|
|
218
|
+
print(order) # Log partially filled orders
|
|
219
|
+
|
|
220
|
+
def on_filled_order(self, order: Order):
|
|
221
|
+
print(order) # Log filled orders
|
|
222
|
+
|
|
223
|
+
def on_bookl1(self, bookl1: BookL1):
|
|
224
|
+
if self.signal: # Check if the signal is active
|
|
225
|
+
# Create a market buy order
|
|
226
|
+
self.create_order(
|
|
227
|
+
symbol="BTCUSDT-PERP.OKX",
|
|
228
|
+
side=OrderSide.BUY,
|
|
229
|
+
type=OrderType.MARKET,
|
|
230
|
+
amount=Decimal("0.1"),
|
|
231
|
+
)
|
|
232
|
+
# Create a market sell order
|
|
233
|
+
self.create_order(
|
|
234
|
+
symbol="BTCUSDT-PERP.OKX",
|
|
235
|
+
side=OrderSide.SELL,
|
|
236
|
+
type=OrderType.MARKET,
|
|
237
|
+
amount=Decimal("0.1"),
|
|
238
|
+
)
|
|
239
|
+
self.signal = False # Deactivate the signal after placing orders
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# Configuration for the trading strategy
|
|
243
|
+
config = Config(
|
|
244
|
+
strategy_id="okx_buy_and_sell",
|
|
245
|
+
user_id="user_test",
|
|
246
|
+
strategy=Demo(),
|
|
247
|
+
basic_config={
|
|
248
|
+
ExchangeType.OKX: BasicConfig(
|
|
249
|
+
api_key=OKX_API_KEY,
|
|
250
|
+
secret=OKX_SECRET,
|
|
251
|
+
passphrase=OKX_PASSPHRASE,
|
|
252
|
+
testnet=True, # Use testnet for safe trading
|
|
253
|
+
)
|
|
254
|
+
},
|
|
255
|
+
public_conn_config={
|
|
256
|
+
ExchangeType.OKX: [
|
|
257
|
+
PublicConnectorConfig(
|
|
258
|
+
account_type=OkxAccountType.DEMO, # Specify demo account type
|
|
259
|
+
)
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
private_conn_config={
|
|
263
|
+
ExchangeType.OKX: [
|
|
264
|
+
PrivateConnectorConfig(
|
|
265
|
+
account_type=OkxAccountType.DEMO, # Specify demo account type
|
|
266
|
+
)
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
# Initialize the trading engine with the configuration
|
|
272
|
+
engine = Engine(config)
|
|
273
|
+
|
|
274
|
+
if __name__ == "__main__":
|
|
275
|
+
try:
|
|
276
|
+
engine.start() # Start the trading engine
|
|
277
|
+
finally:
|
|
278
|
+
engine.dispose() # Ensure resources are cleaned up
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Web Callbacks
|
|
283
|
+
|
|
284
|
+
NexusTrader can host FastAPI endpoints alongside a running strategy. Define an application with
|
|
285
|
+
`nexustrader.web.create_strategy_app`, decorate a method that accepts `self`, and enable the web server in your config.
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
from fastapi import Body
|
|
289
|
+
|
|
290
|
+
from nexustrader.web import create_strategy_app
|
|
291
|
+
from nexustrader.config import WebConfig
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class Demo(Strategy):
|
|
295
|
+
web_app = create_strategy_app(title="Demo strategy API")
|
|
296
|
+
|
|
297
|
+
@web_app.post("/toggle")
|
|
298
|
+
async def on_web_cb(self, payload: dict = Body(...)):
|
|
299
|
+
self.signal = payload.get("signal", True)
|
|
300
|
+
return {"signal": self.signal}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
config = Config(
|
|
304
|
+
strategy_id="demo",
|
|
305
|
+
user_id="user",
|
|
306
|
+
strategy=Demo(),
|
|
307
|
+
basic_config={...},
|
|
308
|
+
public_conn_config={...},
|
|
309
|
+
private_conn_config={...},
|
|
310
|
+
web_config=WebConfig(enabled=True, host="127.0.0.1", port=9000),
|
|
311
|
+
)
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
When the engine starts, it binds the strategy instance to the FastAPI routes and serves them in the background using
|
|
315
|
+
Uvicorn. Routes automatically disappear once the engine stops.
|
|
316
|
+
|
|
317
|
+
This example illustrates how easy it is to switch between different exchanges and strategies by modifying the `config`
|
|
318
|
+
class. For instance, to switch to Binance, you can adjust the configuration as follows, and change the symbol to
|
|
319
|
+
`BTCUSDT-PERP.BINANCE`.
|
|
320
|
+
|
|
321
|
+
```python
|
|
322
|
+
from nexustrader.exchange.binance import BinanceAccountType
|
|
323
|
+
|
|
324
|
+
config = Config(
|
|
325
|
+
strategy_id="buy_and_sell_binance",
|
|
326
|
+
user_id="user_test",
|
|
327
|
+
strategy=Demo(),
|
|
328
|
+
basic_config={
|
|
329
|
+
ExchangeType.BINANCE: BasicConfig(
|
|
330
|
+
api_key=BINANCE_API_KEY,
|
|
331
|
+
secret=BINANCE_SECRET,
|
|
332
|
+
testnet=True, # Use testnet for safe trading
|
|
333
|
+
)
|
|
334
|
+
},
|
|
335
|
+
public_conn_config={
|
|
336
|
+
ExchangeType.BINANCE: [
|
|
337
|
+
PublicConnectorConfig(
|
|
338
|
+
account_type=BinanceAccountType.USD_M_FUTURE_TESTNET, # Specify account type for Binance
|
|
339
|
+
)
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
private_conn_config={
|
|
343
|
+
ExchangeType.BINANCE: [
|
|
344
|
+
PrivateConnectorConfig(
|
|
345
|
+
account_type=BinanceAccountType.USD_M_FUTURE_TESTNET, # Specify account type for Binance
|
|
346
|
+
)
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Multi-Mode Support
|
|
353
|
+
|
|
354
|
+
nexustrader supports multiple modes of operation to cater to different trading strategies and requirements. Each mode
|
|
355
|
+
allows for flexibility in how trading logic is executed based on market conditions or specific triggers.
|
|
356
|
+
|
|
357
|
+
### Event-Driven Mode
|
|
358
|
+
|
|
359
|
+
In this mode, trading logic is executed in response to real-time market events. The methods `on_bookl1`, `on_trade`, and
|
|
360
|
+
`on_kline` are triggered whenever relevant data is updated, allowing for immediate reaction to market changes.
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
class Demo(Strategy):
|
|
364
|
+
def __init__(self):
|
|
365
|
+
super().__init__()
|
|
366
|
+
self.subscribe_bookl1(symbols=["BTCUSDT-PERP.BINANCE"])
|
|
367
|
+
|
|
368
|
+
def on_bookl1(self, bookl1: BookL1):
|
|
369
|
+
# implement the trading logic Here
|
|
370
|
+
pass
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Timer Mode
|
|
374
|
+
|
|
375
|
+
This mode allows you to schedule trading logic to run at specific intervals. You can use the `schedule` method to define
|
|
376
|
+
when your trading algorithm should execute, making it suitable for strategies that require periodic checks or actions.
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
class Demo2(Strategy):
|
|
380
|
+
def __init__(self):
|
|
381
|
+
super().__init__()
|
|
382
|
+
self.schedule(self.algo, trigger="interval", seconds=1)
|
|
383
|
+
|
|
384
|
+
def algo(self):
|
|
385
|
+
# run every 1 second
|
|
386
|
+
# implement the trading logic Here
|
|
387
|
+
pass
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Custom Signal Mode
|
|
391
|
+
|
|
392
|
+
In this mode, trading logic is executed based on custom signals. You can define your own signals and use the
|
|
393
|
+
`on_custom_signal` method to trigger trading actions when these signals are received. This is particularly useful for
|
|
394
|
+
integrating with external systems or custom event sources.
|
|
395
|
+
|
|
396
|
+
```python
|
|
397
|
+
class Demo3(Strategy):
|
|
398
|
+
def __init__(self):
|
|
399
|
+
super().__init__()
|
|
400
|
+
self.signal = True
|
|
401
|
+
|
|
402
|
+
def on_custom_signal(self, signal: object):
|
|
403
|
+
# implement the trading logic Here,
|
|
404
|
+
# signal can be any object, it is up to you to define the signal
|
|
405
|
+
pass
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## Define Your Own Indicator
|
|
409
|
+
|
|
410
|
+
NexusTrader provides a powerful framework for creating custom indicators with built-in warmup functionality. This allows your indicators to automatically fetch historical data and prepare themselves before live trading begins.
|
|
411
|
+
|
|
412
|
+
Here's an example of creating a custom Moving Average indicator with automatic warmup:
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
from collections import deque
|
|
416
|
+
from nexustrader.indicator import Indicator
|
|
417
|
+
from nexustrader.constants import KlineInterval, DataType
|
|
418
|
+
from nexustrader.schema import Kline, BookL1, BookL2, Trade
|
|
419
|
+
from nexustrader.strategy import Strategy
|
|
420
|
+
from nexustrader.exchange.bybit import BybitAccountType
|
|
421
|
+
|
|
422
|
+
class MovingAverageIndicator(Indicator):
|
|
423
|
+
def __init__(self, period: int = 20):
|
|
424
|
+
super().__init__(
|
|
425
|
+
params={"period": period},
|
|
426
|
+
name=f"MA_{period}",
|
|
427
|
+
warmup_period=period * 2, # Define warmup period
|
|
428
|
+
warmup_interval=KlineInterval.MINUTE_1, # Define warmup interval
|
|
429
|
+
)
|
|
430
|
+
self.period = period
|
|
431
|
+
self.prices = deque(maxlen=period)
|
|
432
|
+
self.current_ma = None
|
|
433
|
+
|
|
434
|
+
def handle_kline(self, kline: Kline):
|
|
435
|
+
if not kline.confirm: # Only process confirmed klines
|
|
436
|
+
return
|
|
437
|
+
|
|
438
|
+
self.prices.append(kline.close)
|
|
439
|
+
|
|
440
|
+
# Calculate moving average if we have enough data
|
|
441
|
+
if len(self.prices) >= self.period:
|
|
442
|
+
self.current_ma = sum(self.prices) / len(self.prices)
|
|
443
|
+
|
|
444
|
+
def handle_bookl1(self, bookl1: BookL1):
|
|
445
|
+
pass # Implement if needed
|
|
446
|
+
|
|
447
|
+
def handle_bookl2(self, bookl2: BookL2):
|
|
448
|
+
pass # Implement if needed
|
|
449
|
+
|
|
450
|
+
def handle_trade(self, trade: Trade):
|
|
451
|
+
pass # Implement if needed
|
|
452
|
+
|
|
453
|
+
@property
|
|
454
|
+
def value(self):
|
|
455
|
+
return self.current_ma
|
|
456
|
+
|
|
457
|
+
class MyStrategy(Strategy):
|
|
458
|
+
def __init__(self):
|
|
459
|
+
super().__init__()
|
|
460
|
+
self.symbol = "UNIUSDT-PERP.BYBIT"
|
|
461
|
+
self.ma_20 = MovingAverageIndicator(period=20)
|
|
462
|
+
self.ma_50 = MovingAverageIndicator(period=50)
|
|
463
|
+
|
|
464
|
+
def on_start(self):
|
|
465
|
+
# Subscribe to kline data
|
|
466
|
+
self.subscribe_kline(
|
|
467
|
+
symbols=self.symbol,
|
|
468
|
+
interval=KlineInterval.MINUTE_1,
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
# Register indicators with automatic warmup
|
|
472
|
+
self.register_indicator(
|
|
473
|
+
symbols=self.symbol,
|
|
474
|
+
indicator=self.ma_20,
|
|
475
|
+
data_type=DataType.KLINE,
|
|
476
|
+
account_type=BybitAccountType.LINEAR,
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
self.register_indicator(
|
|
480
|
+
symbols=self.symbol,
|
|
481
|
+
indicator=self.ma_50,
|
|
482
|
+
data_type=DataType.KLINE,
|
|
483
|
+
account_type=BybitAccountType.LINEAR,
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
def on_kline(self, kline: Kline):
|
|
487
|
+
# Wait for indicators to warm up
|
|
488
|
+
if not self.ma_20.is_warmed_up or not self.ma_50.is_warmed_up:
|
|
489
|
+
self.log.info("Indicators still warming up...")
|
|
490
|
+
return
|
|
491
|
+
|
|
492
|
+
if not kline.confirm:
|
|
493
|
+
return
|
|
494
|
+
|
|
495
|
+
if self.ma_20.value and self.ma_50.value:
|
|
496
|
+
self.log.info(
|
|
497
|
+
f"MA20: {self.ma_20.value:.4f}, MA50: {self.ma_50.value:.4f}, "
|
|
498
|
+
f"Current Price: {kline.close:.4f}"
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
# Simple golden cross strategy
|
|
502
|
+
if self.ma_20.value > self.ma_50.value:
|
|
503
|
+
self.log.info("Golden Cross - Bullish signal!")
|
|
504
|
+
elif self.ma_20.value < self.ma_50.value:
|
|
505
|
+
self.log.info("Death Cross - Bearish signal!")
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
#### Key Features of Custom Indicators:
|
|
509
|
+
|
|
510
|
+
1. **Automatic Warmup**: Set `warmup_period` and `warmup_interval` to automatically fetch historical data
|
|
511
|
+
2. **Data Handlers**: Implement `handle_kline`, `handle_bookl1`, `handle_bookl2`, and `handle_trade` as needed
|
|
512
|
+
3. **Value Property**: Expose your indicator's current value through the `value` property
|
|
513
|
+
4. **Warmup Status**: Check `is_warmed_up` property to ensure indicator is ready before using
|
|
514
|
+
5. **Flexible Parameters**: Pass custom parameters through the `params` dictionary
|
|
515
|
+
|
|
516
|
+
This approach ensures your indicators have sufficient historical data before making trading decisions, improving the reliability and accuracy of your trading strategies.
|
|
517
|
+
|
|
518
|
+
## Execution Algorithms
|
|
519
|
+
|
|
520
|
+
NexusTrader provides a powerful execution algorithm framework for implementing advanced order execution strategies like TWAP, VWAP, iceberg orders, and more. This allows you to split large orders into smaller chunks and execute them over time to minimize market impact.
|
|
521
|
+
|
|
522
|
+
### Using TWAP (Time-Weighted Average Price)
|
|
523
|
+
|
|
524
|
+
The built-in `TWAPExecAlgorithm` splits a large order into smaller slices and executes them at regular intervals over a specified time horizon.
|
|
525
|
+
|
|
526
|
+
```python
|
|
527
|
+
from decimal import Decimal
|
|
528
|
+
from datetime import timedelta
|
|
529
|
+
from nexustrader.constants import OrderSide
|
|
530
|
+
from nexustrader.strategy import Strategy
|
|
531
|
+
from nexustrader.engine import Engine
|
|
532
|
+
from nexustrader.execution import TWAPExecAlgorithm
|
|
533
|
+
|
|
534
|
+
class MyStrategy(Strategy):
|
|
535
|
+
def __init__(self):
|
|
536
|
+
super().__init__()
|
|
537
|
+
self.symbol = "BTCUSDT-PERP.BINANCE"
|
|
538
|
+
|
|
539
|
+
def on_start(self):
|
|
540
|
+
self.subscribe_bookl1(self.symbol)
|
|
541
|
+
# Schedule TWAP order placement
|
|
542
|
+
self.schedule(
|
|
543
|
+
func=self.place_twap_order,
|
|
544
|
+
trigger="date",
|
|
545
|
+
run_date=self.clock.utc_now() + timedelta(seconds=10),
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
def place_twap_order(self):
|
|
549
|
+
# Execute 1 BTC over 5 minutes with 30-second intervals (10 slices)
|
|
550
|
+
self.create_algo_order(
|
|
551
|
+
symbol=self.symbol,
|
|
552
|
+
side=OrderSide.BUY,
|
|
553
|
+
amount=Decimal("1.0"),
|
|
554
|
+
exec_algorithm_id="TWAP",
|
|
555
|
+
exec_params={
|
|
556
|
+
"horizon_secs": 300, # Total execution time: 5 minutes
|
|
557
|
+
"interval_secs": 30, # Interval between slices: 30 seconds
|
|
558
|
+
},
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
# Register the execution algorithm with the engine
|
|
562
|
+
engine = Engine(config)
|
|
563
|
+
engine.add_exec_algorithm(algorithm=TWAPExecAlgorithm())
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
#### TWAP Parameters
|
|
567
|
+
|
|
568
|
+
| Parameter | Type | Required | Description |
|
|
569
|
+
|-----------|------|----------|-------------|
|
|
570
|
+
| `horizon_secs` | int | Yes | Total execution time horizon in seconds |
|
|
571
|
+
| `interval_secs` | int | Yes | Interval between order slices in seconds |
|
|
572
|
+
| `use_limit` | bool | No | If True, use limit orders instead of market orders (default: False) |
|
|
573
|
+
| `n_tick_sz` | int | No | Number of tick sizes to offset from best bid/ask for limit orders. Positive = more passive, Negative = more aggressive (default: 0) |
|
|
574
|
+
|
|
575
|
+
#### TWAP with Limit Orders
|
|
576
|
+
|
|
577
|
+
For better price execution, you can use limit orders with price offsets:
|
|
578
|
+
|
|
579
|
+
```python
|
|
580
|
+
self.create_algo_order(
|
|
581
|
+
symbol="BTCUSDT-PERP.OKX",
|
|
582
|
+
side=OrderSide.BUY,
|
|
583
|
+
amount=Decimal("2.0"),
|
|
584
|
+
exec_algorithm_id="TWAP",
|
|
585
|
+
exec_params={
|
|
586
|
+
"horizon_secs": 100,
|
|
587
|
+
"interval_secs": 10,
|
|
588
|
+
"use_limit": True, # Use limit orders
|
|
589
|
+
"n_tick_sz": 1, # Place 1 tick below best ask (for buy)
|
|
590
|
+
},
|
|
591
|
+
reduce_only=True, # Optional: only reduce existing position
|
|
592
|
+
)
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### Creating Custom Execution Algorithms
|
|
596
|
+
|
|
597
|
+
You can create your own execution algorithms by subclassing `ExecAlgorithm`. The key method to implement is `on_order()`, which is called when a new algorithmic order is received.
|
|
598
|
+
|
|
599
|
+
```python
|
|
600
|
+
from decimal import Decimal
|
|
601
|
+
from nexustrader.execution.algorithm import ExecAlgorithm
|
|
602
|
+
from nexustrader.execution.config import ExecAlgorithmConfig
|
|
603
|
+
from nexustrader.execution.schema import ExecAlgorithmOrder
|
|
604
|
+
from nexustrader.execution.constants import ExecAlgorithmStatus
|
|
605
|
+
from nexustrader.schema import Order
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
class MyAlgoConfig(ExecAlgorithmConfig, kw_only=True, frozen=True):
|
|
609
|
+
"""Configuration for custom algorithm."""
|
|
610
|
+
exec_algorithm_id: str = "MY_ALGO"
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
class MyExecAlgorithm(ExecAlgorithm):
|
|
614
|
+
"""Custom execution algorithm example."""
|
|
615
|
+
|
|
616
|
+
def __init__(self, config: MyAlgoConfig | None = None):
|
|
617
|
+
if config is None:
|
|
618
|
+
config = MyAlgoConfig()
|
|
619
|
+
super().__init__(config)
|
|
620
|
+
|
|
621
|
+
def on_order(self, exec_order: ExecAlgorithmOrder):
|
|
622
|
+
"""
|
|
623
|
+
Main entry point - called when create_algo_order() is invoked.
|
|
624
|
+
|
|
625
|
+
Parameters
|
|
626
|
+
----------
|
|
627
|
+
exec_order : ExecAlgorithmOrder
|
|
628
|
+
Contains: primary_oid, symbol, side, total_amount, remaining_amount, params
|
|
629
|
+
"""
|
|
630
|
+
# Access custom parameters
|
|
631
|
+
params = exec_order.params
|
|
632
|
+
my_param = params.get("my_param", "default")
|
|
633
|
+
|
|
634
|
+
# Spawn child orders using available methods:
|
|
635
|
+
# - spawn_market(exec_order, quantity)
|
|
636
|
+
# - spawn_limit(exec_order, quantity, price)
|
|
637
|
+
# - spawn_market_ws / spawn_limit_ws for WebSocket submission
|
|
638
|
+
|
|
639
|
+
# Example: split into two market orders
|
|
640
|
+
half = self.amount_to_precision(
|
|
641
|
+
exec_order.symbol,
|
|
642
|
+
exec_order.total_amount / 2,
|
|
643
|
+
mode="floor"
|
|
644
|
+
)
|
|
645
|
+
self.spawn_market(exec_order, half)
|
|
646
|
+
self.spawn_market(exec_order, exec_order.total_amount - half)
|
|
647
|
+
|
|
648
|
+
def on_spawned_order_filled(self, exec_order: ExecAlgorithmOrder, order: Order):
|
|
649
|
+
"""Called when a spawned order is filled."""
|
|
650
|
+
if exec_order.remaining_amount <= 0:
|
|
651
|
+
self.mark_complete(exec_order)
|
|
652
|
+
|
|
653
|
+
def on_cancel(self, exec_order: ExecAlgorithmOrder):
|
|
654
|
+
"""Handle cancellation request."""
|
|
655
|
+
exec_order.status = ExecAlgorithmStatus.CANCELED
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
#### Key Methods to Override
|
|
659
|
+
|
|
660
|
+
| Method | Description |
|
|
661
|
+
|--------|-------------|
|
|
662
|
+
| `on_order(exec_order)` | **Required.** Main entry point when a new order is received |
|
|
663
|
+
| `on_start()` | Called when the algorithm starts |
|
|
664
|
+
| `on_stop()` | Called when the algorithm stops |
|
|
665
|
+
| `on_cancel(exec_order)` | Called when cancellation is requested |
|
|
666
|
+
| `on_execution_complete(exec_order)` | Called when execution completes |
|
|
667
|
+
| `on_spawned_order_filled(exec_order, order)` | Called when a spawned order is filled |
|
|
668
|
+
| `on_spawned_order_failed(exec_order, order)` | Called when a spawned order fails |
|
|
669
|
+
|
|
670
|
+
#### Utility Methods
|
|
671
|
+
|
|
672
|
+
| Method | Description |
|
|
673
|
+
|--------|-------------|
|
|
674
|
+
| `spawn_market(exec_order, quantity)` | Spawn a market order |
|
|
675
|
+
| `spawn_limit(exec_order, quantity, price)` | Spawn a limit order |
|
|
676
|
+
| `cancel_spawned_order(exec_order, spawned_oid)` | Cancel a spawned order |
|
|
677
|
+
| `mark_complete(exec_order)` | Mark execution as complete |
|
|
678
|
+
| `set_timer(name, interval, callback)` | Set a timer for scheduled execution |
|
|
679
|
+
| `amount_to_precision(symbol, amount)` | Convert amount to market precision |
|
|
680
|
+
| `price_to_precision(symbol, price)` | Convert price to market precision |
|
|
681
|
+
| `min_order_amount(symbol)` | Get minimum order amount |
|
|
682
|
+
| `cache.bookl1(symbol)` | Get current L1 order book |
|
|
683
|
+
|
|
684
|
+
#### Register and Use
|
|
685
|
+
|
|
686
|
+
```python
|
|
687
|
+
engine = Engine(config)
|
|
688
|
+
engine.add_exec_algorithm(algorithm=MyExecAlgorithm())
|
|
689
|
+
|
|
690
|
+
# In strategy:
|
|
691
|
+
self.create_algo_order(
|
|
692
|
+
symbol="BTCUSDT-PERP.BINANCE",
|
|
693
|
+
side=OrderSide.BUY,
|
|
694
|
+
amount=Decimal("1.0"),
|
|
695
|
+
exec_algorithm_id="MY_ALGO",
|
|
696
|
+
exec_params={"my_param": "value"},
|
|
697
|
+
)
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
## Contributing
|
|
701
|
+
|
|
702
|
+
Thank you for considering contributing to nexustrader! We greatly appreciate any effort to help improve the project. If
|
|
703
|
+
you have an idea for an enhancement or a bug fix, the first step is to open
|
|
704
|
+
an [issue](https://github.com/Quantweb3-ai/tradebot-pro/issues) on GitHub. This allows us to discuss your proposal and
|
|
705
|
+
ensure it aligns with the project's goals, while also helping to avoid duplicate efforts.
|
|
706
|
+
|
|
707
|
+
When you're ready to start working on your contribution, please review the guidelines in
|
|
708
|
+
the [CONTRIBUTING.md](./CONTRIBUTING.md) file. Depending on the nature of your contribution, you may also need to sign a
|
|
709
|
+
Contributor License Agreement (CLA) to ensure it can be included in the project.
|
|
710
|
+
|
|
711
|
+
> **Note**
|
|
712
|
+
> Pull requests should be directed to the `main` branch (the default branch), where new features and improvements are
|
|
713
|
+
> integrated before release.
|
|
714
|
+
|
|
715
|
+
Thank you again for your interest in nexustrader! We look forward to reviewing your contributions and collaborating with
|
|
716
|
+
you to make the project even better.
|
|
717
|
+
|
|
718
|
+
## VIP Privileges
|
|
719
|
+
|
|
720
|
+
Trading on our platform is free. Become a VIP customer to enjoy exclusive technical support privileges for $499 per month ([Subscription Here](https://quantweb3.ai/subscribe/ ))—or get VIP status at no cost by opening an account through our partnership links.
|
|
721
|
+
|
|
722
|
+
Our partners include global leading trading platforms like Bybit, OKX, ZFX, Bison and others. By opening an account through our referral links, you'll enjoy these benefits:
|
|
723
|
+
|
|
724
|
+
Instant Account Benefits
|
|
725
|
+
|
|
726
|
+
1. Trading Fee Discounts: Exclusive discounts to lower your trading costs.
|
|
727
|
+
2. VIP Service Support: Contact us after opening your account to become our VIP customer. Enjoy exclusive events and benefits for the ultimate VIP experience.
|
|
728
|
+
|
|
729
|
+
Act now and join our VIP program!
|
|
730
|
+
|
|
731
|
+
> Click the links below to register
|
|
732
|
+
|
|
733
|
+
- [Bybit](https://partner.bybit.com/b/90899)
|
|
734
|
+
- [OKX](http://www.okx.com/join/80353297)
|
|
735
|
+
- [ZFX](https://zfx.link/46dFByp)
|
|
736
|
+
- [Bison](https://m.bison.com/#/register?invitationCode=1002)
|
|
737
|
+
|
|
738
|
+
## Social
|
|
739
|
+
|
|
740
|
+
Connect with us on your favorite platforms:
|
|
741
|
+
|
|
742
|
+
[-000000?logo=x&logoColor=white)](https://x.com/quantweb3_ai) Stay updated with our latest news, features, and announcements.
|
|
743
|
+
|
|
744
|
+
[](https://discord.gg/BR8VGRrXFr) Join our community to discuss ideas, get support, and connect with other users.
|
|
745
|
+
|
|
746
|
+
[](https://t.me/+6e2MtXxoibM2Yzlk) Receive instant updates and engage in real-time discussions.
|
|
747
|
+
|
|
748
|
+
## See Also
|
|
749
|
+
|
|
750
|
+
We recommend exploring related tools and projects that can enhance your trading workflows:
|
|
751
|
+
|
|
752
|
+
- **[Nexus](https://github.com/Quantweb3-ai/nexus):** A robust exchange interface optimization solution that integrates
|
|
753
|
+
seamlessly with trading bots like nexustrader, enabling faster and more reliable trading execution.
|
|
754
|
+
|
|
755
|
+
## License
|
|
756
|
+
|
|
757
|
+
Nexustrader is available on GitHub under the MIT License. Contributions to the project are welcome and require the
|
|
758
|
+
completion of a Contributor License Agreement (CLA). Please review the contribution guidelines and submit a pull
|
|
759
|
+
request. See the [LICENSE](./LICENSE) file for details.
|
|
760
|
+
|
|
761
|
+
## Star History
|
|
762
|
+
|
|
763
|
+
<a href="https://www.star-history.com/#Quantweb3-com/NexusTrader&Date">
|
|
764
|
+
<picture>
|
|
765
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Quantweb3-com/NexusTrader&type=Date&theme=dark" />
|
|
766
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Quantweb3-com/NexusTrader&type=Date" />
|
|
767
|
+
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Quantweb3-com/NexusTrader&type=Date" />
|
|
768
|
+
</picture>
|
|
769
|
+
</a>
|