-
Notifications
You must be signed in to change notification settings - Fork 2
/
mm_kraken_ripio_btc.py
152 lines (120 loc) · 5.47 KB
/
mm_kraken_ripio_btc.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import os
import time
import asyncio
import websockets
import threading
import ccxt
from ripio.trade.client import Client
from dotenv import load_dotenv
load_dotenv()
# Initialize Kraken and Ripio clients
kraken = ccxt.kraken({"apiKey": os.getenv("KRAKEN_API_KEY"), "secret": os.getenv("KRAKEN_SECRET_KEY")})
ripio = Client(api_key=os.getenv("RIPIO_API_KEY"))
# Constants
spread = 0.001
order_amount = 100
order_book_lock = threading.Lock()
offset_orders = set()
created_orders = set()
prev_best_bid = None
prev_best_ask = None
def create_ripio_order(pair, side, amount, price):
global created_orders
balances = ripio.get_user_balances()
if side == "buy":
required_balance = amount * price
currency_code = "USDC"
else: # side == "sell"
required_balance = amount
currency_code = "BTC"
available_balance = 0
for balance in balances:
if balance["currency_code"] == currency_code:
available_balance = float(balance["available_amount"])
break
if available_balance >= required_balance:
params = {
"pair": pair,
"side": side,
"amount": amount,
"type": "limit",
"price": price,
}
response = ripio.create_order(**params)
order_id = response["id"]
created_orders.add(order_id)
else:
print(f"Insufficient {currency_code} balance to create {side} order")
async def kraken_ws_ticker():
global prev_best_bid, prev_best_ask
async with websockets.connect("wss://ws.kraken.com") as websocket:
await websocket.send('{"event": "subscribe", "pair": ["BTC/USDC"], "subscription": {"name": "ticker"}}')
while True:
message = await websocket.recv()
message = eval(message)
if isinstance(message, list) and "ticker" in message:
data = message[1]
order_book_lock.acquire()
best_bid = float(data["b"][0])
best_ask = float(data["a"][0])
# Check if the price change is more than half the spread
if (prev_best_bid is None or abs(prev_best_bid - best_bid) / prev_best_bid > spread / 2) or \
(prev_best_ask is None or abs(prev_best_ask - best_ask) / prev_best_ask > spread / 2):
# Cancel previous orders
for order_id in created_orders:
ripio.cancel_order(order_id)
created_orders.clear()
# Update best bid and ask
prev_best_bid = best_bid
prev_best_ask = best_ask
spread_bid = best_bid * (1 + spread)
spread_ask = best_ask * (1 - spread)
# Create buy and sell orders on Ripio
create_ripio_order("BTC_USDC", "buy", order_amount / spread_bid, spread_bid)
create_ripio_order("BTC_USDC", "sell", order_amount / spread_ask, spread_ask)
order_book_lock.release()
def offset_ripio_order(order_id, side, executed_amount):
global kraken, ripio
# Check available balance on Kraken
kraken_balance = kraken.fetch_balance()
btc_balance = kraken_balance["total"]["BTC"]
usdc_balance = kraken_balance["total"]["USDC"]
# Determine the side of the order to be placed on Kraken
kraken_side = "sell" if side == "buy" else "buy"
# Calculate the amount to be offset on Kraken
if kraken_side == "buy":
usdc_amount = executed_amount * kraken.fetch_ticker("BTC/USDC")["last"]
if usdc_amount <= usdc_balance:
kraken.create_market_order("BTC/USDC", kraken_side, usdc_amount)
print(f"Offset {kraken_side} order of {usdc_amount} USDC created on Kraken")
else:
print("Insufficient USDC balance on Kraken to offset the order")
else: # kraken_side == "sell"
if executed_amount <= btc_balance:
kraken.create_market_order("BTC/USDC", kraken_side, executed_amount)
print(f"Offset {kraken_side} order of {executed_amount} BTC created on Kraken")
else:
print("Insufficient BTC balance on Kraken to offset the order")
async def monitor_ripio_orders():
global created_orders
while True:
for order_id in created_orders:
order = ripio.get_order_by_id(order_id)
if order["status"] in ["executed_completely", "executed_partially"]:
executed_amount = order["executed_amount"]
offset_ripio_order(order_id, order["side"], executed_amount)
print(f"Order {order_id} on Ripio has been offset on Kraken")
# Remove the executed order from the list
created_orders.remove(order_id)
# Create a new order on Ripio with the same side, amount, and price
new_order_id = create_ripio_order("BTC_USDC", order["side"], order["price"], order["requested_amount"])
created_orders.append(new_order_id)
print(f"New order created on Ripio with ID: {new_order_id}")
await asyncio.sleep(10)
# Run the websocket connection and order monitoring in separate threads
kraken_ws_thread = threading.Thread(target=lambda: asyncio.run(kraken_ws_ticker()))
monitor_ripio_orders_thread = threading.Thread(target=lambda: asyncio.run(monitor_ripio_orders()))
kraken_ws_thread.start()
monitor_ripio_orders_thread.start()
kraken_ws_thread.join()
monitor_ripio_orders_thread.join()