Advertisement
den4ik2003

Untitled

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