Advertisement
den4ik2003

Untitled

Apr 5th, 2025
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.92 KB | None | 0 0
  1. from threading import Thread
  2. import numpy as np
  3. import time
  4. from copy import copy
  5. from binance.spot import Spot
  6. from utility import make_client
  7. import fcntl
  8.  
  9. class Volume:
  10. def reopen(self):
  11. try:
  12. self.target_f.close()
  13. except Exception as e:
  14. print(e)
  15. try:
  16. self.target_f = open(f"/mnt/pt_telemetry/{self.group}", "r")
  17. except Exception as e:
  18. print(e)
  19.  
  20. def __init__(self, group):
  21. self.threads = []
  22. self.binance = Spot('', '')
  23. self.pwr = 0
  24. self.volumes = []
  25. self.bgt = int(time.time())
  26. self.group = group
  27. self.reopen()
  28. self.price = 0
  29. self.last_len = 0
  30. self.last_mm_info_t = 0
  31.  
  32. def get_mm_lvls(self):
  33. lines = self.mm_bests_f.readlines()
  34. print('get_mm_lvls len:', len(lines))
  35. if len(lines) < 1:
  36. return
  37. if lines[-1] != '':
  38. bests_info_dict = eval(lines[-1].rstrip())
  39. else:
  40. if len(lines) < 2:
  41. return
  42. bests_info_dict = eval(lines[-2].rstrip())
  43. try:
  44. t = int(bests_info_dict['ts'])
  45. self.last_mm_info_t = t
  46. print('get_mm_lvls:', bests_info_dict)
  47. print('delta', int(time.time()*1000) - t)
  48. if int(time.time()*1000) - t > 1000: # считаем, что 1000ms достаточно, чтобы выставление мм-ордера догло до биржи
  49. return
  50. print('delta t < 1000')
  51. except:
  52. print('Exception get_mm_lvls():', line[-2:])
  53. return
  54. return (float(bests_info_dict['ask_price']), float(bests_info_dict['bid_price']))
  55.  
  56. def target(self):
  57. try:
  58. fcntl.flock(self.target_f, fcntl.LOCK_EX)
  59. lines = self.target_f.readlines()
  60. clen = len(lines)
  61. if self.last_len == 0 and clen == 0:
  62. self.reopen()
  63. self.last_len = len(lines)
  64. fcntl.flock(self.target_f, fcntl.LOCK_UN)
  65. for line in lines:
  66. if 'price' in line:
  67. self.price = float(eval(line.split(' price ')[1])['price'])
  68. except Exception as e:
  69. print(e)
  70. self.target_f = open(f"/mnt/pt_telemetry/{self.group}", "r")
  71. return self.price
  72.  
  73. def _process(self,
  74. market, daily_volume, left_bound,
  75. right_bound, history_mode, threshold,
  76. tight_spread, smart, smart_spread, close_candles,
  77. tight_min_base,
  78. tight_min_quote,
  79. buy_ratio
  80. ):
  81. self.mm_bests_f = open(f"/mnt/mm_bid_ask/{market.symbol[1].upper()}_{market.symbol[2].upper()}_{market.market}", "r") # если есть файл
  82.  
  83. book = market.get_info()['book']
  84. self.price = (book['ask_price'] + book['bid_price']) / 2
  85. bal_f = open(f"/mnt/volume_telemetry/{market.symbol[1].upper()}_{market.symbol[2].upper()}_{market.market}", "a")
  86.  
  87. flush = lambda _: bal_f.flush()
  88. log = lambda name, obj: flush(bal_f.write(f'{int(time.time() * 1000)} {name} {obj}\n'))
  89.  
  90. log("alert", {'op': 'start'})
  91. price = (book['ask_price'] + book['bid_price']) / 2
  92. counter = 0
  93. self.step = 0.1 ** market.symbol[3]
  94. market_old = market
  95. if smart:
  96. bal_f2 = open(f"/mnt/wolume_telemetry/{market.symbol[1].upper()}_{market.symbol[2].upper()}_{market.market}", "a")
  97. market2 = make_client(market.market, market.symbol[1] + '_' + market.symbol[2], market.symbol[3:], 'W', {})
  98. market_new = market2
  99. else:
  100. bal_f2 = bal_f
  101. market2 = market
  102.  
  103. flush2 = lambda _: bal_f2.flush()
  104. log2 = lambda name, obj: flush2(bal_f2.write(f'{int(time.time() * 1000)} {name} {obj}\n'))
  105.  
  106. last_price = None
  107. last_day = 0
  108. last_5m = None
  109. iter_len = [0]
  110. while True:
  111. market, market2 = market2, market
  112. bg = time.time()
  113. print(bg, flush=True)
  114. coef = 1
  115. cd = 10
  116. try:
  117. ##########
  118. info = market_old.get_info()
  119. log('book', info['book'])
  120. log('balance', info['balance'])
  121. public_trades = market_old.get_new_public_trades()
  122. private_trades = market_old.get_new_private_trades()
  123. log('public_trades', public_trades)
  124. log('private_trades', private_trades)
  125.  
  126. if smart:
  127. print('bebra', flush=True)
  128. info = market_new.get_info()
  129. log2('book', info['book'])
  130. print(info, flush=True)
  131. log2('balance', info['balance'])
  132. public_trades = market_new.get_new_public_trades()
  133. private_trades = market_new.get_new_private_trades()
  134. log2('public_trades', public_trades)
  135. log2('private_trades', private_trades)
  136.  
  137. print('started', flush=True)
  138. try:
  139. fees_res = market.get_fees()
  140. if type(fees_res) == tuple:
  141. taker_fees, maker_fees = fees_res[0], fees_res[1]
  142. log('fees', {'taker': taker_fees, 'maker': maker_fees})
  143. else:
  144. print('not tuple fees result', fees_res)
  145.  
  146. except Exception as e:
  147. print(f'exception: {e} ({market.market})', flush=True)
  148. log('alert', {'op': 'stop', 'type':'fees', 'msg':f'{e}'})
  149. return
  150.  
  151. if history_mode:
  152. cur_day = int(time.time()) // 86400
  153. cur_5m = (int(time.time()) % 86400) // 288
  154. if cur_day > last_day:
  155. kline_history = self.binance.klines(symbol='BTCUSDT', interval='5m', limit=289, endTime = cur_day * 86400000)[:-1]
  156. volume_1d = np.sum(float(kline[7]) for kline in kline_history)
  157. last_day = cur_day
  158. kline_5m = kline_history[:cur_5m + 1]
  159. else:
  160. volume_1d = float(self.binance.ticker_24hr(symbol='BTCUSDT')['quoteVolume'])
  161. kline_5m = self.binance.klines(symbol='BTCUSDT', interval='5m', limit=60)
  162. print(f'len: {len(kline_5m)}')
  163. pmn = np.min([float(z[4]) for z in kline_5m])
  164. pmx = np.max([float(z[4]) for z in kline_5m])
  165.  
  166. V = daily_volume / float(volume_1d) * float(kline_5m[-2][7])
  167. if V >= 100:
  168. mean_cd = 5
  169. elif V >= 50:
  170. mean_cd = 10
  171. elif V >= 25:
  172. mean_cd = 60
  173. elif V >= 10:
  174. mean_cd = 120
  175. else:
  176. mean_cd = 180
  177. mean_vol = V * ((mean_cd + np.mean(iter_len)) / 300)
  178. print(np.mean(iter_len))
  179. cd = min(120, max(1, np.random.uniform(mean_cd / 10, mean_cd * 1.9)))
  180. norm_price = (float(kline_5m[-1][4]) - pmn) / (pmx - pmn) * (right_bound - left_bound) + left_bound
  181. step_size = 0.1 ** market.symbol[3]
  182.  
  183. book_time_before = time.time()*1000 # debug
  184. print('book time before:', book_time_before) # debug
  185. info = market.get_info()
  186. book_time_after = time.time()*1000 # debug
  187. print('book time after:', book_time_after) # debug
  188. print('book latency:', book_time_after - book_time_before) # debug
  189. book = info['book']
  190. print(book)
  191. if book['bid_price'] == 0:
  192. print('bid_price == 0')
  193. time.sleep(10)
  194. continue
  195.  
  196. bal = info['balance']
  197. spread = book['ask_price'] / book['bid_price'] - 1
  198. if spread >= 0.1:
  199. print('spread > 10%')
  200. counter += 1
  201. if counter >= 10:
  202. log('alert', {'op': 'stop', 'type':'spread'})
  203. return
  204. time.sleep(10)
  205. continue
  206. else:
  207. counter = 0
  208. print(f'balances: {bal['base']} {bal['quote']}')
  209. print(f'spread: {spread} {market.market}')
  210.  
  211. mm_lvls = self.get_mm_lvls()
  212. print('info book:', book)
  213. print('mm_info_t - book_t:', int((book_time_before + book_time_after) / 2) - self.last_mm_info_t) # debug
  214. print('delta now - mm_info_t:', int(time.time()*1000) - self.last_mm_info_t) # debug
  215. if mm_lvls != None:
  216. book['ask_price'] = min(book['ask_price'], mm_lvls[0])
  217. book['bid_price'] = max(book['bid_price'], mm_lvls[1])
  218. if mm_lvls[0] < book['ask_price'] or mm_lvls[1] > book['bid_price']:
  219. print(int(time.time()*1000), 'MM update detected', book, mm_lvls)
  220.  
  221. cur_price = (book['bid_price'] + step_size) + (book['ask_price'] - book['bid_price'] - 2 * step_size) * norm_price
  222. target_price = self.target()
  223. try:
  224. print(target_price)
  225. print(f'target: {target_price} (clip inside ({target_price * (1 - threshold / 100)}; {target_price * (1 + threshold / 100)}))')
  226. cur_price = np.clip(cur_price, target_price * (1 - threshold / 100), target_price * (1 + threshold / 100))
  227. except Exception as e:
  228. print(e)
  229. print(mean_vol)
  230. qty = min((bal['base'] * cur_price + bal['quote']) / 3, 3.5 + max(1.6, np.random.normal(mean_vol, mean_vol / 3))) / cur_price
  231. cur_price = float(f'%.{market.symbol[3]}f' % cur_price)
  232. print(f"iteration: {qty}, {cur_price}, {norm_price}")
  233. if last_price != None:
  234. if abs(cur_price / last_price - 1) >= 0.08:
  235. log('alert', {'op': 'stop'})
  236. break
  237.  
  238. if close_candles:
  239. cur_5m = (int(time.time()) % 86400) // 300
  240. if last_5m == None or cur_5m > last_5m and last_price != None:
  241. cur_price = last_price
  242. last_5m = cur_5m
  243.  
  244. # book = market.get_info()['book']
  245. print(f'{cur_price} {book['bid_price'] + step_size} {book['ask_price'] - step_size}')
  246. print(f'{market.market} {book}')
  247. if bal['base'] < qty:
  248. print("bal[base] < qty")
  249. print(last_price)
  250. if last_price != None and abs(book['ask_price'] / last_price - 1) <= 0.01:
  251. market.new_limit(book['ask_price'], qty, True)
  252. elif bal['quote'] < qty * cur_price:
  253. print("bal[quote] < qty * cur_price")
  254. if last_price != None and abs(book['bid_price'] / last_price - 1) <= 0.01:
  255. market.new_limit(book['bid_price'], qty, False)
  256. else:
  257. if cur_price <= book['ask_price'] - step_size / 2 and cur_price >= book['bid_price'] + step_size / 2:
  258. print(f"proceeding {type(market)}")
  259. threads = []
  260. if np.random.randint(0, 2):
  261. threads.append(Thread(target=market.new_limit, args=(cur_price, qty, False)))
  262. threads[-1].start()
  263. threads.append(Thread(target=market2.new_limit, args=(cur_price, qty, True)))
  264. threads[-1].start()
  265. else:
  266. threads.append(Thread(target=market.new_limit, args=(cur_price, qty, True)))
  267. threads[-1].start()
  268. threads.append(Thread(target=market2.new_limit, args=(cur_price, qty, False)))
  269. threads[-1].start()
  270. for t in threads:
  271. t.join()
  272. elif tight_spread:
  273. print(f"tight {type(market)}")
  274. print('ask', book['ask_price'])
  275. print('bid', book['bid_price'])
  276.  
  277. threads = []
  278. is_buy = (self.target() >= book['ask_price'])
  279. if is_buy:
  280. print('buying in tight')
  281. qty = max(qty, 6 / book['ask_price'])
  282. print('qty', qty)
  283. if bal['quote'] - qty * book['ask_price'] >= tight_min_quote:
  284. print('valid balance for buyback')
  285. threads.append(Thread(target=market.new_limit, args=(book['ask_price'], qty, True)))
  286. threads[-1].start()
  287. cur_price = book['ask_price']
  288. else:
  289. print('invalid balance for buyback')
  290. print(bal['quote'], qty, tight_min_quote)
  291. else:
  292. print('selling in tight')
  293. qty = max(qty, 6 / book['bid_price'])
  294. print('qty', qty)
  295. if bal['base'] - qty >= tight_min_base:
  296. print('valid balance for buyback')
  297. threads.append(Thread(target=market.new_limit, args=(book['bid_price'], qty, False)))
  298. threads[-1].start()
  299. cur_price = book['bid_price']
  300. else:
  301. print('invalid balance for buyback')
  302. print(bal['base'], qty, tight_min_base)
  303. for t in threads:
  304. t.join()
  305.  
  306. last_price = cur_price
  307.  
  308. except Exception as e:
  309. print(f'exception: {e} ({market.market})')
  310. try:
  311. market.cancel_open_orders()
  312. except Exception as e:
  313. print(f'exception cancel: {e} ({market.market})')
  314. finally:
  315. if len(iter_len) == 100:
  316. iter_len = iter_len[1:]
  317. iter_len.append(time.time() - bg)
  318. time.sleep(cd)
  319.  
  320. def add_market(self, market, daily_volume, left_bound=1/4, right_bound=3/4, history_mode=False, threshold=1.5, tight_spread=False, smart_daily_volume=0, smart_spread_size=2, close_candles=False, tight_min_base=0, tight_min_quote=0, buy_ratio=0.5):
  321. daily_volume = float(daily_volume)
  322. left_bound = float(left_bound)
  323. right_bound = float(right_bound)
  324. threshold = float(threshold)
  325. if threshold < 0:
  326. threshold = None
  327. if smart_daily_volume:
  328. self.threads.append(Thread(target=self._process, args=(market, smart_daily_volume / 2, left_bound, right_bound, history_mode, threshold, tight_spread, True, smart_spread_size, close_candles, tight_min_base, tight_min_quote, buy_ratio)))
  329. if daily_volume:
  330. self.threads.append(Thread(target=self._process, args=(market, daily_volume, left_bound, right_bound, history_mode, threshold, tight_spread, False, 0, close_candles, tight_min_base, tight_min_quote, buy_ratio)))
  331.  
  332. def run_event_loop(self):
  333. for thread in self.threads:
  334. thread.start()
  335. for thread in self.threads:
  336. thread.join()
  337.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement