forked from hummingbot/hummingbot
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy patharbitrage_with_smart_component.py
98 lines (87 loc) · 5.2 KB
/
arbitrage_with_smart_component.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
from decimal import Decimal
from hummingbot.core.rate_oracle.rate_oracle import RateOracle
from hummingbot.smart_components.executors.arbitrage_executor.arbitrage_executor import ArbitrageExecutor
from hummingbot.smart_components.executors.arbitrage_executor.data_types import ArbitrageConfig, ExchangePair
from hummingbot.strategy.script_strategy_base import ScriptStrategyBase
class ArbitrageWithSmartComponent(ScriptStrategyBase):
# Parameters
exchange_pair_1 = ExchangePair(exchange="binance", trading_pair="MATIC-USDT")
exchange_pair_2 = ExchangePair(exchange="uniswap_polygon_mainnet", trading_pair="WMATIC-USDT")
order_amount = Decimal("50") # in base asset
min_profitability = Decimal("0.004")
markets = {exchange_pair_1.exchange: {exchange_pair_1.trading_pair},
exchange_pair_2.exchange: {exchange_pair_2.trading_pair}}
active_buy_arbitrages = []
active_sell_arbitrages = []
closed_arbitrage_executors = []
def on_tick(self):
self.cleanup_arbitrages()
if len(self.active_buy_arbitrages) < 1:
buy_arbitrage_executor = self.create_arbitrage_executor(
buying_exchange_pair=self.exchange_pair_1,
selling_exchange_pair=self.exchange_pair_2,
)
if buy_arbitrage_executor:
self.active_buy_arbitrages.append(buy_arbitrage_executor)
if len(self.active_sell_arbitrages) < 1:
sell_arbitrage_executor = self.create_arbitrage_executor(
buying_exchange_pair=self.exchange_pair_2,
selling_exchange_pair=self.exchange_pair_1,
)
if sell_arbitrage_executor:
self.active_sell_arbitrages.append(sell_arbitrage_executor)
def on_stop(self):
for arbitrage in self.active_buy_arbitrages:
arbitrage.terminate_control_loop()
for arbitrage in self.active_sell_arbitrages:
arbitrage.terminate_control_loop()
def create_arbitrage_executor(self, buying_exchange_pair: ExchangePair, selling_exchange_pair: ExchangePair):
try:
base_asset_for_selling_exchange = self.connectors[selling_exchange_pair.exchange].get_available_balance(
selling_exchange_pair.trading_pair.split("-")[0])
if self.order_amount > base_asset_for_selling_exchange:
self.logger().info(f"Insufficient balance in exchange {selling_exchange_pair.exchange} "
f"to sell {selling_exchange_pair.trading_pair.split('-')[0]} "
f"Actual: {base_asset_for_selling_exchange} --> Needed: {self.order_amount}")
return
# Harcoded for now since we don't have a price oracle for WMATIC (CoinMarketCap rate source is requested and coming)
pair_conversion = selling_exchange_pair.trading_pair.replace("W", "")
price = RateOracle.get_instance().get_pair_rate(pair_conversion)
quote_asset_for_buying_exchange = self.connectors[buying_exchange_pair.exchange].get_available_balance(
buying_exchange_pair.trading_pair.split("-")[1])
if self.order_amount * price > quote_asset_for_buying_exchange:
self.logger().info(f"Insufficient balance in exchange {buying_exchange_pair.exchange} "
f"to buy {buying_exchange_pair.trading_pair.split('-')[1]} "
f"Actual: {quote_asset_for_buying_exchange} --> Needed: {self.order_amount * price}")
return
arbitrage_config = ArbitrageConfig(
buying_market=buying_exchange_pair,
selling_market=selling_exchange_pair,
order_amount=self.order_amount,
min_profitability=self.min_profitability,
)
arbitrage_executor = ArbitrageExecutor(strategy=self,
arbitrage_config=arbitrage_config)
return arbitrage_executor
except Exception:
self.logger().error(f"Error creating executor to buy on {buying_exchange_pair.exchange} and sell on {selling_exchange_pair.exchange}")
def format_status(self) -> str:
status = []
status.extend([f"Closed Arbtriages: {len(self.closed_arbitrage_executors)}"])
for arbitrage in self.closed_arbitrage_executors:
status.extend(arbitrage.to_format_status())
status.extend([f"Active Arbitrages: {len(self.active_sell_arbitrages) + len(self.active_buy_arbitrages)}"])
for arbitrage in self.active_sell_arbitrages:
status.extend(arbitrage.to_format_status())
for arbitrage in self.active_buy_arbitrages:
status.extend(arbitrage.to_format_status())
return "\n".join(status)
def cleanup_arbitrages(self):
for arbitrage in self.active_buy_arbitrages:
if arbitrage.is_closed:
self.closed_arbitrage_executors.append(arbitrage)
self.active_buy_arbitrages.remove(arbitrage)
for arbitrage in self.active_sell_arbitrages:
if arbitrage.is_closed:
self.closed_arbitrage_executors.append(arbitrage)
self.active_sell_arbitrages.remove(arbitrage)