· 2 months ago · Jul 14, 2025, 06:05 PM
1#!/usr/bin/env python3
2# -------------------------------------------------------------------------------------------------
3# Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
4# https://nautechsystems.io
5#
6# Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
7# You may not use this file except in compliance with the License.
8# You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15# -------------------------------------------------------------------------------------------------
16
17import sys
18from decimal import Decimal
19
20from nautilus_trader.live.node import TradingNode
21from nautilus_trader.trading.controller import Controller
22from nautilus_trader.adapters.bybit.common.enums import BybitProductType
23from nautilus_trader.config import (
24 TradingNodeConfig,
25 CacheConfig,
26 LiveExecEngineConfig,
27 InstrumentProviderConfig,
28 LoggingConfig,
29)
30from nautilus_trader.model.identifiers import InstrumentId, TraderId
31from nautilus_trader.adapters.bybit.config import BybitDataClientConfig, BybitExecClientConfig
32from nautilus_trader.adapters.bybit.factories import BybitLiveDataClientFactory, BybitLiveExecClientFactory
33from nautilus_trader.examples.strategies.ema_cross import EMACross, EMACrossConfig
34from nautilus_trader.model.data import BarType
35
36from .config import get_settings, Settings
37
38def get_trading_node(settings: Settings, product_type: BybitProductType) -> TradingNode:
39 node_config = _get_node_config(settings, product_type)
40 node = TradingNode(config=node_config)
41 return node
42
43
44
45def _get_node_config(settings: Settings, product_type: BybitProductType) -> TradingNodeConfig:
46 exec_engine = LiveExecEngineConfig(
47 reconciliation=True,
48 reconciliation_lookback_mins=100,
49 )
50 print(f"BYBIT API KEY: {settings.BYBIT_API_KEY}")
51
52 trader_id = TraderId("MRE-test")
53 node_config = TradingNodeConfig(
54 cache=CacheConfig(),
55 trader_id=trader_id,
56 logging=LoggingConfig(log_level="INFO", use_pyo3=True),
57 exec_engine=exec_engine,
58 data_clients={
59 "BYBIT": BybitDataClientConfig(
60 api_key=settings.BYBIT_API_KEY,
61 api_secret=settings.BYBIT_API_SECRET,
62 base_url_http=None, # Override with custom endpoint
63 instrument_provider=InstrumentProviderConfig(load_all=True),
64 product_types=[product_type], # Will load all instruments
65 testnet=False,
66 ),
67 },
68 exec_clients={
69 "BYBIT": BybitExecClientConfig(
70 api_key=settings.BYBIT_API_KEY,
71 api_secret=settings.BYBIT_API_SECRET,
72 base_url_http=None, # Override with custom endpoint
73 base_url_ws_private=None, # Override with custom endpoint
74 instrument_provider=InstrumentProviderConfig(load_all=True),
75 product_types=[product_type],
76 testnet=False,
77 max_retries=3,
78 retry_delay_initial_ms=1_000,
79 retry_delay_max_ms=10_000,
80 ),
81 },
82 timeout_connection=20.0,
83 timeout_reconciliation=10.0,
84 timeout_portfolio=10.0,
85 timeout_disconnection=10.0,
86 timeout_post_stop=5.0,
87 )
88 return node_config
89
90
91def main():
92 try:
93 settings = get_settings()
94 product_type = BybitProductType.LINEAR
95 symbol = f"ETHUSDT-{product_type.value.upper()}"
96 trade_size = Decimal("0.010")
97 node = get_trading_node(settings, product_type)
98 strat_config = EMACrossConfig(
99 instrument_id=InstrumentId.from_str(f"{symbol}.BYBIT"),
100 external_order_claims=[InstrumentId.from_str(f"{symbol}.BYBIT")],
101 bar_type=BarType.from_str(f"{symbol}.BYBIT-1-MINUTE-LAST-EXTERNAL"),
102 fast_ema_period=50,
103 slow_ema_period=200,
104 trade_size=trade_size,
105 order_id_tag="001",
106 )
107 strategy = EMACross(config=strat_config)
108 # node.trader.add_strategy(strategy)
109 node.add_data_client_factory("BYBIT", BybitLiveDataClientFactory)
110 node.add_exec_client_factory("BYBIT", BybitLiveExecClientFactory)
111 node.build()
112 node.run()
113 controller = Controller(node)
114 controller.create_strategy(strategy)
115 except KeyboardInterrupt:
116 print("Interrupted by user")
117 sys.exit(0)
118 except Exception as e:
119 print(f"Fatal error in running trading node: {e}", file=sys.stderr)
120 sys.exit(1)
121 finally:
122 if node:
123 node.dispose()
124
125
126# Stop and dispose of the node with SIGINT/CTRL+C
127if __name__ == "__main__":
128 main()