Skip to content

Commit be25c7b

Browse files
committed
Continue additional order types for Bybit
1 parent 57914f0 commit be25c7b

File tree

6 files changed

+293
-52
lines changed

6 files changed

+293
-52
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env python3
2+
# -------------------------------------------------------------------------------------------------
3+
# Copyright (C) 2015-2024 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+
17+
from decimal import Decimal
18+
19+
from nautilus_trader.adapters.bybit.common.enums import BybitProductType
20+
from nautilus_trader.adapters.bybit.config import BybitDataClientConfig
21+
from nautilus_trader.adapters.bybit.config import BybitExecClientConfig
22+
from nautilus_trader.adapters.bybit.factories import BybitLiveDataClientFactory
23+
from nautilus_trader.adapters.bybit.factories import BybitLiveExecClientFactory
24+
from nautilus_trader.config import InstrumentProviderConfig
25+
from nautilus_trader.config import LiveExecEngineConfig
26+
from nautilus_trader.config import LoggingConfig
27+
from nautilus_trader.config import TradingNodeConfig
28+
from nautilus_trader.examples.strategies.ema_cross_stop_entry import EMACrossStopEntry
29+
from nautilus_trader.examples.strategies.ema_cross_stop_entry import EMACrossStopEntryConfig
30+
from nautilus_trader.live.node import TradingNode
31+
from nautilus_trader.model.data import BarType
32+
from nautilus_trader.model.identifiers import InstrumentId
33+
from nautilus_trader.model.identifiers import TraderId
34+
35+
36+
# *** THIS IS A TEST STRATEGY WITH NO ALPHA ADVANTAGE WHATSOEVER. ***
37+
# *** IT IS NOT INTENDED TO BE USED TO TRADE LIVE WITH REAL MONEY. ***
38+
39+
# SPOT/LINEAR
40+
product_type = BybitProductType.LINEAR
41+
symbol = f"ETHUSDT-{product_type.value.upper()}"
42+
trade_size = Decimal("0.010")
43+
44+
# Configure the trading node
45+
config_node = TradingNodeConfig(
46+
trader_id=TraderId("TESTER-001"),
47+
logging=LoggingConfig(log_level="INFO", use_pyo3=True),
48+
exec_engine=LiveExecEngineConfig(
49+
reconciliation=True,
50+
reconciliation_lookback_mins=1440,
51+
),
52+
data_clients={
53+
"BYBIT": BybitDataClientConfig(
54+
api_key=None, # 'BYBIT_API_KEY' env var
55+
api_secret=None, # 'BYBIT_API_SECRET' env var
56+
base_url_http=None, # Override with custom endpoint
57+
instrument_provider=InstrumentProviderConfig(load_all=True),
58+
product_types=[product_type],
59+
testnet=False, # If client uses the testnet
60+
),
61+
},
62+
exec_clients={
63+
"BYBIT": BybitExecClientConfig(
64+
api_key=None, # 'BYBIT_API_KEY' env var
65+
api_secret=None, # 'BYBIT_API_SECRET' env var
66+
base_url_http=None, # Override with custom endpoint
67+
base_url_ws=None, # Override with custom endpoint
68+
instrument_provider=InstrumentProviderConfig(load_all=True),
69+
product_types=[product_type],
70+
testnet=False, # If client uses the testnet
71+
),
72+
},
73+
timeout_connection=30.0,
74+
timeout_reconciliation=10.0,
75+
timeout_portfolio=10.0,
76+
timeout_disconnection=10.0,
77+
timeout_post_stop=5.0,
78+
)
79+
80+
# Instantiate the node with a configuration
81+
node = TradingNode(config=config_node)
82+
83+
# Configure your strategy
84+
strat_config = EMACrossStopEntryConfig(
85+
instrument_id=InstrumentId.from_str(f"{symbol}.BYBIT"),
86+
external_order_claims=[InstrumentId.from_str(f"{symbol}.BYBIT")],
87+
bar_type=BarType.from_str(f"{symbol}.BYBIT-1-MINUTE-LAST-EXTERNAL"),
88+
fast_ema_period=10,
89+
slow_ema_period=20,
90+
atr_period=20,
91+
trailing_atr_multiple=3.0,
92+
trailing_offset=Decimal("0.010"),
93+
trailing_offset_type="BASIS_POINTS",
94+
trigger_type="LAST_TRADE",
95+
trade_size=Decimal("0.010"),
96+
)
97+
# Instantiate your strategy
98+
strategy = EMACrossStopEntry(config=strat_config)
99+
100+
# Add your strategies and modules
101+
node.trader.add_strategy(strategy)
102+
103+
# Register your client factories with the node (can take user defined factories)
104+
node.add_data_client_factory("BYBIT", BybitLiveDataClientFactory)
105+
node.add_exec_client_factory("BYBIT", BybitLiveExecClientFactory)
106+
node.build()
107+
108+
109+
# Stop and dispose of the node with SIGINT/CTRL+C
110+
if __name__ == "__main__":
111+
try:
112+
node.run()
113+
finally:
114+
node.dispose()
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env python3
2+
# -------------------------------------------------------------------------------------------------
3+
# Copyright (C) 2015-2024 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+
17+
from decimal import Decimal
18+
19+
from nautilus_trader.adapters.bybit.common.enums import BybitProductType
20+
from nautilus_trader.adapters.bybit.config import BybitDataClientConfig
21+
from nautilus_trader.adapters.bybit.config import BybitExecClientConfig
22+
from nautilus_trader.adapters.bybit.factories import BybitLiveDataClientFactory
23+
from nautilus_trader.adapters.bybit.factories import BybitLiveExecClientFactory
24+
from nautilus_trader.config import InstrumentProviderConfig
25+
from nautilus_trader.config import LiveExecEngineConfig
26+
from nautilus_trader.config import LoggingConfig
27+
from nautilus_trader.config import TradingNodeConfig
28+
from nautilus_trader.examples.strategies.ema_cross_trailing_stop import EMACrossTrailingStop
29+
from nautilus_trader.examples.strategies.ema_cross_trailing_stop import EMACrossTrailingStopConfig
30+
from nautilus_trader.live.node import TradingNode
31+
from nautilus_trader.model.data import BarType
32+
from nautilus_trader.model.identifiers import InstrumentId
33+
from nautilus_trader.model.identifiers import TraderId
34+
35+
36+
# *** THIS IS A TEST STRATEGY WITH NO ALPHA ADVANTAGE WHATSOEVER. ***
37+
# *** IT IS NOT INTENDED TO BE USED TO TRADE LIVE WITH REAL MONEY. ***
38+
39+
# SPOT/LINEAR
40+
product_type = BybitProductType.LINEAR
41+
symbol = f"ETHUSDT-{product_type.value.upper()}"
42+
trade_size = Decimal("0.010")
43+
44+
# Configure the trading node
45+
config_node = TradingNodeConfig(
46+
trader_id=TraderId("TESTER-001"),
47+
logging=LoggingConfig(log_level="INFO", use_pyo3=True),
48+
exec_engine=LiveExecEngineConfig(
49+
reconciliation=True,
50+
reconciliation_lookback_mins=1440,
51+
),
52+
data_clients={
53+
"BYBIT": BybitDataClientConfig(
54+
api_key=None, # 'BYBIT_API_KEY' env var
55+
api_secret=None, # 'BYBIT_API_SECRET' env var
56+
base_url_http=None, # Override with custom endpoint
57+
instrument_provider=InstrumentProviderConfig(load_all=True),
58+
product_types=[product_type],
59+
testnet=False, # If client uses the testnet
60+
),
61+
},
62+
exec_clients={
63+
"BYBIT": BybitExecClientConfig(
64+
api_key=None, # 'BYBIT_API_KEY' env var
65+
api_secret=None, # 'BYBIT_API_SECRET' env var
66+
base_url_http=None, # Override with custom endpoint
67+
base_url_ws=None, # Override with custom endpoint
68+
instrument_provider=InstrumentProviderConfig(load_all=True),
69+
product_types=[product_type],
70+
testnet=False, # If client uses the testnet
71+
),
72+
},
73+
timeout_connection=30.0,
74+
timeout_reconciliation=10.0,
75+
timeout_portfolio=10.0,
76+
timeout_disconnection=10.0,
77+
timeout_post_stop=5.0,
78+
)
79+
80+
# Instantiate the node with a configuration
81+
node = TradingNode(config=config_node)
82+
83+
# Configure your strategy
84+
strat_config = EMACrossTrailingStopConfig(
85+
instrument_id=InstrumentId.from_str(f"{symbol}.BYBIT"),
86+
external_order_claims=[InstrumentId.from_str(f"{symbol}.BYBIT")],
87+
bar_type=BarType.from_str(f"{symbol}.BYBIT-1-MINUTE-LAST-EXTERNAL"),
88+
fast_ema_period=10,
89+
slow_ema_period=20,
90+
atr_period=20,
91+
trailing_atr_multiple=3.0,
92+
trailing_offset_type="BASIS_POINTS",
93+
trigger_type="LAST_TRADE",
94+
trade_size=Decimal("0.010"),
95+
)
96+
# Instantiate your strategy
97+
strategy = EMACrossTrailingStop(config=strat_config)
98+
99+
# Add your strategies and modules
100+
node.trader.add_strategy(strategy)
101+
102+
# Register your client factories with the node (can take user defined factories)
103+
node.add_data_client_factory("BYBIT", BybitLiveDataClientFactory)
104+
node.add_exec_client_factory("BYBIT", BybitLiveExecClientFactory)
105+
node.build()
106+
107+
108+
# Stop and dispose of the node with SIGINT/CTRL+C
109+
if __name__ == "__main__":
110+
try:
111+
node.run()
112+
finally:
113+
node.dispose()

nautilus_trader/adapters/bybit/common/enums.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,10 @@ def __init__(self) -> None:
240240
b: a for a, b in self.bybit_to_nautilus_order_side.items()
241241
}
242242
self.bybit_to_nautilus_order_type = {
243-
BybitOrderType.MARKET: OrderType.MARKET,
244-
BybitOrderType.MARKET: OrderType.MARKET_IF_TOUCHED,
245-
BybitOrderType.MARKET: OrderType.STOP_MARKET,
246-
BybitOrderType.MARKET: OrderType.TRAILING_STOP_MARKET,
247-
BybitOrderType.LIMIT: OrderType.LIMIT,
248-
BybitOrderType.LIMIT: OrderType.LIMIT_IF_TOUCHED,
249-
BybitOrderType.LIMIT: OrderType.STOP_LIMIT,
250-
BybitOrderType.LIMIT: OrderType.TRAILING_STOP_LIMIT,
243+
(BybitOrderType.MARKET, BybitStopOrderType.NONE): OrderType.MARKET,
244+
(BybitOrderType.LIMIT, BybitStopOrderType.NONE): OrderType.LIMIT,
245+
(BybitOrderType.MARKET, BybitStopOrderType.STOP): OrderType.STOP_MARKET,
246+
(BybitOrderType.LIMIT, BybitStopOrderType.STOP): OrderType.STOP_LIMIT,
251247
}
252248
self.nautilus_to_bybit_order_type = {
253249
b: a for a, b in self.bybit_to_nautilus_order_type.items()
@@ -272,15 +268,19 @@ def __init__(self) -> None:
272268
BybitOrderStatus.FILLED: OrderStatus.FILLED,
273269
BybitOrderStatus.CANCELED: OrderStatus.CANCELED,
274270
BybitOrderStatus.PARTIALLY_FILLED: OrderStatus.PARTIALLY_FILLED,
271+
BybitOrderStatus.DEACTIVATED: OrderStatus.EXPIRED,
275272
}
276273
self.nautilus_to_bybit_order_status = {
277274
b: a for a, b in self.bybit_to_nautilus_order_status.items()
278275
}
276+
self.bybit_to_nautilus_trigger_type = {
277+
BybitTriggerType.NONE: TriggerType.NO_TRIGGER,
278+
BybitTriggerType.LAST_PRICE: TriggerType.LAST_TRADE,
279+
BybitTriggerType.MARK_PRICE: TriggerType.MARK_PRICE,
280+
BybitTriggerType.INDEX_PRICE: TriggerType.INDEX_PRICE,
281+
}
279282
self.nautilus_to_bybit_trigger_type = {
280-
TriggerType.DEFAULT: BybitTriggerType.LAST_PRICE,
281-
TriggerType.LAST_TRADE: BybitTriggerType.LAST_PRICE,
282-
TriggerType.MARK_PRICE: BybitTriggerType.MARK_PRICE,
283-
TriggerType.INDEX_PRICE: BybitTriggerType.INDEX_PRICE,
283+
b: a for a, b in self.bybit_to_nautilus_trigger_type.items()
284284
}
285285

286286
# klines
@@ -308,6 +308,10 @@ def __init__(self) -> None:
308308
self.valid_order_types = {
309309
OrderType.MARKET,
310310
OrderType.LIMIT,
311+
OrderType.MARKET_IF_TOUCHED,
312+
OrderType.LIMIT_IF_TOUCHED,
313+
OrderType.STOP_MARKET,
314+
OrderType.STOP_LIMIT,
311315
}
312316
self.valid_time_in_force = {
313317
TimeInForce.GTC,
@@ -330,10 +334,17 @@ def parse_bybit_order_side(self, order_side: BybitOrderSide) -> OrderSide:
330334
def parse_nautilus_order_side(self, order_side: OrderSide) -> BybitOrderSide:
331335
return check_dict_keys(order_side, self.nautilus_to_bybit_order_side)
332336

333-
def parse_bybit_order_type(self, order_type: BybitOrderType) -> OrderType:
334-
return check_dict_keys(order_type, self.bybit_to_nautilus_order_type)
337+
def parse_bybit_order_type(
338+
self,
339+
order_type: BybitOrderType,
340+
stop_order_type: BybitStopOrderType,
341+
) -> OrderType:
342+
return check_dict_keys((order_type, stop_order_type), self.bybit_to_nautilus_order_type)
335343

336-
def parse_nautilus_order_type(self, order_type: OrderType) -> BybitOrderType:
344+
def parse_nautilus_order_type(
345+
self,
346+
order_type: OrderType,
347+
) -> tuple[BybitOrderType, BybitStopOrderType]:
337348
return check_dict_keys(order_type, self.nautilus_to_bybit_order_type)
338349

339350
def parse_nautilus_time_in_force(self, time_in_force: TimeInForce) -> BybitTimeInForce:
@@ -347,6 +358,9 @@ def parse_nautilus_time_in_force(self, time_in_force: TimeInForce) -> BybitTimeI
347358
def parse_nautilus_trigger_type(self, trigger_type: TriggerType) -> BybitTriggerType:
348359
return check_dict_keys(trigger_type, self.nautilus_to_bybit_trigger_type)
349360

361+
def parse_bybit_trigger_type(self, trigger_type: BybitTriggerType) -> TriggerType:
362+
return check_dict_keys(trigger_type, self.bybit_to_nautilus_trigger_type)
363+
350364
def parse_trigger_direction(
351365
self,
352366
order_type: OrderType,

0 commit comments

Comments
 (0)