Advertisement
den4ik2003

Untitled

Mar 14th, 2025
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 26.70 KB | None | 0 0
  1. import asyncio
  2. import logging
  3. import os
  4. import time
  5. import json
  6. import subprocess
  7. import sys
  8. import psutil
  9. from datetime import datetime
  10. from pathlib import Path
  11. from aiogram.types import Message
  12. from aiogram.enums import ParseMode
  13. from aiogram import Bot, Dispatcher, types
  14. from aiogram.filters.command import Command
  15. from aiogram import F
  16. from pathlib import Path
  17. from aiogram.exceptions import TelegramBadRequest
  18. from apscheduler.schedulers.asyncio import AsyncIOScheduler
  19. import signal
  20.  
  21. logging.basicConfig(level=logging.INFO)
  22.  
  23. scheduler = AsyncIOScheduler()
  24. bot = Bot(token="7848354217:AAFqy-o0vsCFVUwvOZCFeEwN4BQEGcAvfME")
  25. # bot = Bot(token="8075248495:AAF5sWpFJYOPmaN__vutIaZ-73J44FVti-g")
  26.  
  27. dp = Dispatcher()
  28.  
  29. def parse_admins_json():
  30.     with open('admins.json', 'r') as admins_f:
  31.         uids = json.loads(''.join(admins_f.readlines()).replace(' ', '').replace('\n', ''))
  32.        
  33.     with open('/home/ubuntu/tgbot/alerts.json', 'r') as alert_f:
  34.         uids_blocked_alarams = json.loads(''.join(alert_f.readlines()).replace(' ', '').replace('\n', ''))
  35.  
  36.         for uid in uids:
  37.             if uid not in uids_blocked_alarams:
  38.                 uids_blocked_alarams[uid] = {}
  39.  
  40.     return (uids, uids_blocked_alarams)
  41.  
  42.  
  43. available_uids, uids_blocked_alarams = parse_admins_json()
  44.  
  45. super_admins = {
  46.     "6351928464": "Mansur",
  47.     "6049031402":"Murat",
  48.     "377206035":"Denis",
  49.     "5885283978":"Ibragim",
  50. }
  51.  
  52. alarm_types = {
  53.     'wide-spread': 'mm_wide_spread',
  54.     'buy-occupancy': 'mm_buy_occupancy_rate',
  55.     'sell-occupancy': 'mm_sell_occupancy_rate',
  56.     'narrow-spread': 'mm_narrow_spread',
  57.     'zero-balance': 'mm_zero_balance',
  58.     'base-low-balance': 'mm_base_low_balance',
  59.     'quote-low-balance': 'mm_quote_low_balance',
  60.     'no-trades': 'vol_no_trades'
  61. }
  62.  
  63. alarm_type_to_answer = {
  64.     'mm_wide_spread': 'Wide spread > 2%',
  65.     'mm_buy_occupancy_rate': 'Buy side occupancy rate',
  66.     'mm_sell_occupancy_rate': 'Sell side occupancy rate',
  67.     'mm_narrow_spread': 'Narrow spread < 0.02%',
  68.     'mm_zero_balance': 'Zero balance',
  69.     'mm_base_low_balance': 'Base balance < 10% of Zero base',
  70.     'mm_quote_low_balance': 'Quote balance < 10% of Zero quote',
  71.     'vol_no_trades': 'No trades within last 15 minutes',
  72. }
  73.  
  74. price_checker_upd_p = {}
  75.  
  76. path_to_mm_balances_dir = '/mnt/mm_telemetry'
  77. path_to_vol_balances_dir = '/mnt/volume_telemetry'
  78. balance_state = {}
  79. prev_wide_spread = {}
  80. stopped = [[], []]
  81.  
  82. alarm_last_time = {}
  83.  
  84. async def verification(uid):
  85.     if f"{uid}" in available_uids:
  86.         return True
  87.     else:
  88.         return False
  89.  
  90.  
  91. @dp.message(Command("start"))
  92. async def start(message: types.Message):
  93.     is_verified = await verification(message.from_user.id)
  94.     if not is_verified:
  95.         await message.answer("You are not verified so i don't know who are you\nPlease contact @saushkin_den if you think this is a mistake")
  96.         return
  97.  
  98.     await message.answer(f"Welcome to EchoBot controller, {available_uids[str(message.from_user.id)]}!\n") # Call \"/help\" too see the available commands")
  99.  
  100.  
  101. @dp.message(Command("ping"))
  102. async def ping(message: types.Message):
  103.     is_verified = await verification(message.from_user.id)
  104.     if not is_verified:
  105.         await message.answer("You are not in whitelist")
  106.         return
  107.    
  108.     if str(message.from_user.id) in super_admins:
  109.         await message.answer("You have super-admin rights")
  110.     else:
  111.         await message.answer("You have user rights")
  112.        
  113.  
  114. @dp.message(Command("check_user_alarms"))
  115. async def check_user_alarms(message: types.Message):
  116.     result = ''
  117.     if str(message.from_user.id) in super_admins:
  118.         for user in uids_blocked_alarams:
  119.            
  120.             result += f'\n~~~ {available_uids[user]} ({user}) disabled alarms list ~~~'
  121.             init_result = result
  122.  
  123.             if len(uids_blocked_alarams[user]) == 0:
  124.                 result += '\n- No disabled\n'
  125.                 continue
  126.  
  127.             for pair in uids_blocked_alarams[user]:
  128.  
  129.                 if len(uids_blocked_alarams[user][pair]) == 0:
  130.                     continue
  131.  
  132.                 result += ('\n' + pair + ':')
  133.  
  134.                 for alarm in uids_blocked_alarams[user][pair]:
  135.                     result += '\n- ' + alarm_type_to_answer[alarm]
  136.  
  137.             if result == init_result: # то есть нет ни одного аларма
  138.                 result += '\n- No disabled\n'
  139.  
  140.             result += '\n'
  141.  
  142.         await message.reply(result)
  143.        
  144.     else:
  145.         await message.reply("You haven't super admin rights to do it")
  146.  
  147.  
  148. @dp.message(Command("get_disabled_alarms"))
  149. async def get_disabled_alarms(message: types.Message):
  150.     is_verified = await verification(message.from_user.id)
  151.     if not is_verified:
  152.         await message.answer("You are not in whitelist")
  153.         return
  154.  
  155.     if len(uids_blocked_alarams[str(message.from_user.id)]) == 0:
  156.         await message.reply('No disabled alarms')
  157.         return
  158.  
  159.     answer = init_answer = 'List of disabled alarms\n------------'
  160.  
  161.     for pair in uids_blocked_alarams[str(message.from_user.id)]:
  162.  
  163.         if len(uids_blocked_alarams[str(message.from_user.id)][pair]) == 0:
  164.             continue
  165.  
  166.         answer += ('\n' + pair + ':')
  167.         for alarm in uids_blocked_alarams[str(message.from_user.id)][pair]:
  168.             answer += ('\n- ' + alarm_type_to_answer[alarm])
  169.  
  170.         answer += '\n'
  171.  
  172.     if answer == init_answer:
  173.         await message.reply('No disabled alarms')
  174.     else:
  175.         await message.reply(answer)
  176.  
  177.  
  178. @dp.message(F.text.lower().contains('/add_admin_'))
  179. async def add_admin(message: Message):
  180.     add_id = message.text.split('_')[2].upper()
  181.     name = message.text.split('_')[3].upper()
  182.     if str(message.from_user.id) in super_admins:
  183.         if str(message.from_user.id) not in available_uids:
  184.             available_uids[str(message.from_user.id)] = super_admins[str(message.from_user.id)]
  185.             uids_blocked_alarams[str(message.from_user.id)] = {}
  186.  
  187.         available_uids[add_id] = name[0].upper() + name[1:].lower()
  188.         uids_blocked_alarams[add_id] = {}
  189.  
  190.         with open('/home/ubuntu/tgbot/admins.json', 'w') as admins_f:
  191.             admins_f.write(json.dumps(available_uids))
  192.            
  193.         with open('/home/ubuntu/tgbot/alerts.json', 'w') as alerts_f:
  194.             alerts_f.write(json.dumps(uids_blocked_alarams))
  195.  
  196.         await message.reply(f"{available_uids[add_id]} with {add_id} uid was added as admin")
  197.  
  198.     else:
  199.         await message.reply("You haven't super admin rights to do it")
  200.        
  201.  
  202. @dp.message(F.text.lower().contains('/alarm_'))
  203. async def add_filter(message: Message):
  204.     is_verified = await verification(message.from_user.id)
  205.     if not is_verified:
  206.         await message.answer("You are not verified so i don't know who are you")
  207.         return
  208.  
  209.     if message.text.split('_')[1].lower() == 'reset':
  210.         if len(message.text.split('_')) < 4:
  211.             await message.answer("Wrong number of arguments!\nExample: /alarm_reset_DAG_MEXC")
  212.             return
  213.        
  214.         coin = message.text.split('_')[2]
  215.         exchange = '_'.join(message.text.split('_')[3:])
  216.  
  217.         name = (coin + "_USDT_" + exchange).upper()
  218.         uids_blocked_alarams[str(message.from_user.id)][name] = []
  219.  
  220.         await message.answer("Reset completed")
  221.  
  222.     elif message.text.split('_')[1].lower() == 'disable':
  223.         if len(message.text.split('_')) < 5:
  224.             await message.answer("Wrong number of arguments!\nExample: /alarm_disable_wide-spread_DAG_MEXC")
  225.             return
  226.  
  227.         alarm_type = message.text.split('_')[2].lower()
  228.         coin = message.text.split('_')[3]
  229.         exchange = '_'.join(message.text.split('_')[4:])
  230.  
  231.         name = (coin + "_USDT_" + exchange).upper()
  232.  
  233.         if name in uids_blocked_alarams[str(message.from_user.id)]:
  234.             if alarm_type in uids_blocked_alarams[str(message.from_user.id)][name]:
  235.                 await message.answer('Already have this type')
  236.                 return
  237.             elif alarm_type == 'all' and len(uids_blocked_alarams[str(message.from_user.id)][name]) == len(alarm_types):
  238.                 await message.answer('Already have this type')
  239.                 return
  240.        
  241.         if alarm_type == 'all':
  242.  
  243.             if name not in uids_blocked_alarams[str(message.from_user.id)]:
  244.                 uids_blocked_alarams[str(message.from_user.id)][name] = []
  245.  
  246.             for alarm_t in alarm_types:
  247.                 uids_blocked_alarams[str(message.from_user.id)][name].append(alarm_types[alarm_t])
  248.         else:
  249.             if alarm_type not in alarm_types:
  250.                 all_types = '\n- '.join(alarm_types.keys())
  251.                 await message.answer(f'Unknown alarm type: {alarm_type}\nAllowed types:\n- {all_types}')
  252.                 return
  253.  
  254.             if name not in uids_blocked_alarams[str(message.from_user.id)]:
  255.                 uids_blocked_alarams[str(message.from_user.id)][name] = []
  256.  
  257.             uids_blocked_alarams[str(message.from_user.id)][name].append(alarm_types[alarm_type])
  258.  
  259.         await message.answer("Add filter completed")
  260.        
  261.     else:
  262.         await message.answer('Unknown type, allowed only: \"reset\" and \"disable\"')
  263.  
  264.     with open('/home/ubuntu/tgbot/alerts.json', 'w') as alert_f:
  265.         alert_f.write(json.dumps(uids_blocked_alarams))
  266.    
  267.  
  268. @dp.message(F.text) # КОСТЫЛЬ!! нужны фильтры, сейчас НЕЛЬЗЯ эту функцию поднимать выше
  269. async def bad_message(message: Message):
  270.     is_verified = await verification(message.from_user.id)
  271.     if not is_verified:
  272.         await message.answer("You are not verified so i don't know who are you\nplease contact @saushkin_den if you think this is a mistake")
  273.         return
  274.  
  275.     await message.answer("I don't understand you")
  276.  
  277.  
  278. async def send_message_to_users(msg):
  279.     for user_id in available_uids:
  280.         try:
  281.             await bot.send_message(text=msg, chat_id=user_id)
  282.         except:
  283.             continue
  284.  
  285.  
  286. async def broadcast_alarm_message_to_users(msg, pair, alarm_type):
  287.     pair = pair.upper()
  288.  
  289.     if pair not in alarm_last_time:
  290.         alarm_last_time[pair] = {}
  291.  
  292.     if alarm_type in alarm_last_time[pair]:
  293.         if int(time.time()) - alarm_last_time[pair][alarm_type] >= 600:
  294.             for user_id in available_uids:
  295.                 try:
  296.                     if pair in uids_blocked_alarams[user_id] and alarm_type in uids_blocked_alarams[user_id][pair]:
  297.                         continue
  298.                     else:    
  299.                         await bot.send_message(text=msg, chat_id=user_id)
  300.  
  301.                 except Exception as e:
  302.                     print(f'Exception broadcast_alarm_message_to_users: {e}')
  303.                    
  304.                     continue
  305.            
  306.             alarm_last_time[pair][alarm_type] = int(time.time())
  307.     else:
  308.         for user_id in available_uids:
  309.             try:
  310.                 if pair in uids_blocked_alarams[user_id] and alarm_type in uids_blocked_alarams[user_id][pair]:
  311.                     continue
  312.                 else:
  313.                     await bot.send_message(text=msg, chat_id=user_id)
  314.             except:
  315.                 continue
  316.            
  317.         alarm_last_time[pair][alarm_type] = int(time.time())
  318.  
  319.  
  320.  
  321. async def mm_calculate_lob_occupancy_rate(name, orders_log, decoded):
  322.     orders = json.loads(''.join(orders_log.split(' ')[2:]).replace("'", '"'))
  323.     asks_sum = sum([float(order['quantity']) for order in orders['ask']])
  324.     bids_sum = sum([float(order['quantity']) * float(order['price']) for order in orders['bid']])
  325.    
  326.     print('asks_sum', asks_sum, 'bids_sum', bids_sum)
  327.  
  328.     for line in decoded:
  329.         if 'position' in line:
  330.             position = json.loads(''.join(line.split(' ')[2:]).replace("'", '"'))
  331.  
  332.             if 'total_buy_quote' not in position or 'total_sell_base' not in position: # пока нет этого поля, чтобы исключения не летели постоянно
  333.                 print("'total_buy_quote' not in position")
  334.                 break
  335.  
  336.             if 0.1 * float(position['total_buy_quote']) > bids_sum:
  337.                 await broadcast_alarm_message_to_users(
  338.                     f"MARKET MAKING ALARM: {name} buy order book occupancy rate < 10%\nCurrent bids amount: {bids_sum}\nTotal buy quote parameter: {float(position['total_buy_quote'])}",
  339.                     name, 'mm_buy_occupancy_rate'
  340.                 )
  341.  
  342.             if 0.1 * float(position['total_sell_base']) > asks_sum:
  343.                 await broadcast_alarm_message_to_users(
  344.                     f"MARKET MAKING ALARM: {name} sell order book occupancy rate < 10%\nCurrent asks quantity: {asks_sum}\nTotal sell base parameter: {float(position['total_sell_base'])}",
  345.                     name, 'mm_sell_occupancy_rate'
  346.                 )
  347.  
  348.             break
  349.  
  350.  
  351. async def balance_checker(bot: Bot):
  352.     mm_files_path = [path_to_mm_balances_dir + '/' + file.name for file in Path(path_to_mm_balances_dir).iterdir() if file.is_file()]
  353.     volume_files_path = [path_to_vol_balances_dir + '/' + file.name for file in Path(path_to_vol_balances_dir).iterdir() if file.is_file()]
  354.  
  355.     for balance_file in mm_files_path:
  356.         p = subprocess.Popen(['tail', '-30', balance_file],shell=False, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
  357.         res, err = p.communicate()
  358.         if not err:
  359.             name = balance_file.split('/')[-1]
  360.             decoded = res.decode().split('\n')
  361.             used = set()
  362.             for line in decoded[::-1]:
  363.                 try:
  364.                     time = str(datetime.fromtimestamp(int(int(line.split(' ')[0]) / 1000)))
  365.                 except Exception as e:
  366.                     if line != '':
  367.                         print(e)
  368.                         print(f'error parse {name}')
  369.                     continue
  370.  
  371.                 splitted = line.split(' ')
  372.  
  373.                 if len(splitted) < 3:
  374.                     continue
  375.  
  376.                 if 'stop' in line:
  377.                     if name in stopped[0]:
  378.                         break
  379.                     stopped[0].append(name)
  380.                     await send_message_to_users(f'MARKET MAKING ALARM: {name} bot was stopped at {time}')
  381.                     break
  382.  
  383.                 if name in stopped[0]:
  384.                     stopped[0].remove(name)
  385.                     await send_message_to_users(f'MARKET MAKING ALARM: {name} bot was restarted')
  386.  
  387.                 if 'cashout' in line or 'buyback' in line:
  388.                     continue
  389.  
  390.                 msg_type = splitted[1]
  391.                 if msg_type in used:
  392.                     continue
  393.                 used.add(msg_type)
  394.  
  395.                 try:
  396.                     info_dict = eval(''.join(splitted[2:]).replace("'", '"'))
  397.                 except Exception as e:
  398.                     print(name, f'{e}')
  399.                     continue
  400.  
  401.                 if msg_type == 'book':
  402.                     if float(info_dict['ask_price']) == 0:
  403.                         pass
  404.                         # await send_message_to_users(f'ALARM: {name} bid price = 0')
  405.                     else:
  406.                         spread_size = (float(info_dict['ask_price']) - float(info_dict['bid_price'])) / float(info_dict['ask_price'])
  407.                         ask = float(info_dict['ask_price'])
  408.                         bid = float(info_dict['bid_price'])
  409.                         if spread_size > 0.02:
  410.                             await broadcast_alarm_message_to_users(
  411.                                 f'MARKET MAKING ALARM: {name} spread > 2%\nspread: {round(spread_size * 100, 2)}%\nask: {ask}\nbid: {bid}',
  412.                                 name, 'mm_wide_spread'
  413.                             )
  414.                         elif spread_size < 0.0002:
  415.                             await broadcast_alarm_message_to_users(
  416.                                 f'MARKET MAKING ALARM: {name} spread < 0.02%\nspread: {round(spread_size * 100, 2)}%\nask: {ask}\nbid: {bid}',
  417.                                 name, 'mm_narrow_spread'
  418.                             )
  419.  
  420.                 elif msg_type == 'balance':
  421.                     base, quote = float(info_dict['base']), float(info_dict['quote'])
  422.                     new_balances = {"time": time, "base": base, 'quote': quote}
  423.  
  424.                     zero_base, zero_quote = await extract_zero_position(decoded[::-1]) # TODO: обработать только что созданные файлы
  425.  
  426.                     if zero_base == 0 and zero_quote == 0:
  427.                         await broadcast_alarm_message_to_users(
  428.                             f'MARKET MAKING ALARM: {name} zero base or quote balance',
  429.                             name, 'mm_zero_balance'
  430.                         )
  431.                         continue
  432.  
  433.                     if base < 0.1 * zero_base:
  434.                         await broadcast_alarm_message_to_users(
  435.                             f'MARKET MAKING ALARM: {name} base balance lower than critical (<10%)\nbase: {base} ~~~ zero base: {zero_base}',
  436.                             name, 'mm_base_low_balance'
  437.                         )
  438.  
  439.                     if quote < 0.1 * zero_quote:
  440.                         await broadcast_alarm_message_to_users(
  441.                             f'MARKET MAKING ALARM: {name} balance lower than critical (<10%)\nquote: {quote} ~~~ zero quote: {zero_quote}',
  442.                             name, 'mm_quote_low_balance'
  443.                         )
  444.  
  445.                     if name not in balance_state:
  446.                         balance_state[name] = new_balances
  447.                         continue
  448.  
  449.                     free_delta = abs(new_balances['base'] - balance_state[name]['base']) / balance_state[name]['base']
  450.                     locked_delta = abs(new_balances['quote'] - balance_state[name]['quote']) / balance_state[name]['quote']
  451.  
  452.                     if free_delta > 0.1 or locked_delta > 0.1:
  453.                         prev_bal = json.dumps(balance_state[name])
  454.                         new_bal = json.dumps(new_balances)
  455.                         balance_state[name] = new_balances # update
  456.                         # await send_message_to_users(f'ALARM: {name} balance > 10% change:\n  new: {new_bal}\n  previous: {prev_bal}')
  457.  
  458.                 elif msg_type == 'orders':
  459.                     await mm_calculate_lob_occupancy_rate(name, line, decoded[::-1])
  460.         else:
  461.             print(err.decode())
  462.  
  463.     # for balance_file in volume_files_path:
  464.     #     p = subprocess.Popen(['tail', '-1', balance_file],shell=False, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
  465.     #     res, err = p.communicate()
  466.     #     if not err:
  467.     #         name = balance_file.split('/')[-1]
  468.     #         try:
  469.     #             time = str(datetime.fromtimestamp(int(int(res.decode().split(' ')[0]) / 1000)))
  470.     #         except:
  471.     #             print(f'error parse {name} ')
  472.     #             continue
  473.  
  474.     #         if 'stop' in res.decode():
  475.     #             if name in stopped[1]:
  476.     #                 continue
  477.     #             stopped[1].append(name)
  478.     #             await send_message_to_users(f'VOLUME ALARM: {name} bot was stopped at {time}')
  479.     #             continue
  480.  
  481.     #         if name in stopped[1]:
  482.     #             stopped[1].remove(name)
  483.     #             await send_message_to_users(f'VOLUME ALARM: {name} bot was restarted')
  484.  
  485.     #         msg_type = res.decode().split(' ')[1]
  486.     #         info_dict = eval(''.join(res.decode().split(' ')[2:]).replace("'", '"'))
  487.  
  488.     #         if msg_type == 'balance':
  489.     #             base, quote = float(info_dict['base']), float(info_dict['quote'])
  490.     #             new_balances = {"time": time, "base": base, 'quote': quote}
  491.            
  492.     #             if base < 10 and quote < 10: # в теории норм обработать надо
  493.     #                 await send_message_to_users(f'VOLUME ALARM: {name} quote or base balance = 0')
  494.     #                 continue
  495.  
  496.     #             if name not in balance_state:
  497.     #                 balance_state[name] = new_balances
  498.     #                 continue
  499.  
  500.     #             free_delta = abs(new_balances['base'] - balance_state[name]['base']) / max(30, balance_state[name]['base'])
  501.     #             locked_delta = abs(new_balances['quote'] - balance_state[name]['quote']) / max(30, balance_state[name]['quote'])
  502.  
  503.     #             if free_delta > 0.1 or locked_delta > 0.1:
  504.     #                 prev_bal = json.dumps(balance_state[name])
  505.     #                 new_bal = json.dumps(new_balances)
  506.     #                 balance_state[name] = new_balances # update
  507.     #                 # await send_message_to_users(f'VOLUME ALARM: {name} balance > 10% change:\n  previous: {prev_bal}\n  new: {new_bal}')
  508.     #     else:
  509.     #         print(err.decode())
  510.  
  511.     print(balance_state)
  512.  
  513.  
  514. async def volume_health_trades_checker(bot: Bot):
  515.     volume_files_path = [path_to_vol_balances_dir + '/' + file.name for file in Path(path_to_vol_balances_dir).iterdir() if file.is_file()]
  516.  
  517.     bound_time = (int(time.time()) - 900)*1000 # -15 minutes
  518.  
  519.     for balance_file in volume_files_path:
  520.         p = subprocess.Popen(['tail', '-5000', balance_file],shell=False, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
  521.         res, err = p.communicate()
  522.         if not err:
  523.             name = balance_file.split('/')[-1]
  524.             decoded = res.decode().split('\n')
  525.            
  526.             if len(decoded) <= 2:
  527.                 continue
  528.  
  529.             line = ''
  530.             if 'stop' in decoded[-1]:
  531.                 line = decoded[-1]
  532.             elif 'stop' in decoded[-2]:
  533.                 line = decoded[-2]
  534.    
  535.             if line != '':
  536.                 try:
  537.                     t = str(datetime.fromtimestamp(int(int(line.split(' ')[0]) / 1000)))
  538.                 except Exception as e:
  539.                     if line != '':
  540.                         print(e)
  541.                         print(f'error parse {name}')
  542.                     continue
  543.  
  544.                 if name not in stopped[1]:
  545.                     stopped[1].append(name)
  546.                     stop_type = 'Spread > 10% or Price change > 8%'
  547.                     msg=' '
  548.                     if 'fees' in line:
  549.                         stop_type = 'Fees increased'
  550.                         try:
  551.                             d = json.loads(''.join(line.split(' ')[2:]).replace("'", '"'))
  552.                             if 'msg' in d:
  553.                                 msg = '\n' + str(d['msg'])
  554.                         except:
  555.                             pass
  556.  
  557.                     await send_message_to_users(f'VOLUME ALARM: {name} bot was stopped at {t} due to {stop_type}{msg}')
  558.                 continue
  559.  
  560.             for line in decoded[::-1]:
  561.                        
  562.                 if name in stopped[1]:
  563.                     stopped[1].remove(name)
  564.                     await send_message_to_users(f'VOLUME ALARM: {name} bot was restarted')
  565.                     continue
  566.  
  567.                 try:                
  568.                     if int(line.split(' ')[0]) < bound_time:
  569.                         await broadcast_alarm_message_to_users(f'VOLUME ALARM: {name} no private trades within 15 minutes', name, 'vol_no_trades')
  570.                         break
  571.  
  572.                     if 'private_trades' in line:
  573.                         if ''.join(line.split(' ')[2:]) != '[]':
  574.                             break
  575.  
  576.                 except Exception as e:
  577.                     if line != '':
  578.                         print(f'volume_health_trades_checker exception: {e}')
  579.                         print('volume_health_trades_checker exeception:', name, line)
  580.                     continue
  581.  
  582.  
  583. async def extract_zero_position(decoded):
  584.     for line in decoded:
  585.         if 'position' in line:
  586.             position = json.loads(''.join(line.split(' ')[2:]).replace("'", '"'))
  587.             return (float(position['zero_base']), float(position['zero_quote']))
  588.  
  589.     return (0, 0)
  590.            
  591.  
  592. async def price_checker(bot: Bot):
  593.     mm_files_path = [path_to_mm_balances_dir + '/' + file.name for file in Path(path_to_mm_balances_dir).iterdir() if file.is_file()]
  594.  
  595.     for balance_file in mm_files_path:
  596.         p = subprocess.Popen(['tail', '-100', balance_file],shell=False, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
  597.         res, err = p.communicate()
  598.  
  599.         if not err:
  600.             name = balance_file.split('/')[-1]
  601.             decoded = res.decode().split('\n')
  602.             for line in decoded[::-1]:
  603.                 if 'stop' in line:
  604.                     break
  605.                 if 'book' in line:
  606.                     book = json.loads(''.join(line.split(' ')[2:]).replace("'", '"'))
  607.                     mid_price = (float(book['ask_price']) + float(book['bid_price'])) / 2
  608.  
  609.                     # print('Price checker', name, price_checker_upd_p)
  610.                     # print('book', name, book)
  611.  
  612.                     if float(book['ask_price']) == 0 and float(book['bid_price']) == 0:
  613.                         continue
  614.  
  615.                     if name not in price_checker_upd_p:
  616.                         price_checker_upd_p[name] = [0, 0]
  617.  
  618.                     if price_checker_upd_p[name][1] != 0:
  619.                         if mid_price > 1.05 * price_checker_upd_p[name][1] or mid_price < 0.95 * price_checker_upd_p[name][1]:
  620.                             prev_time = str(datetime.fromtimestamp(price_checker_upd_p[name][0]))
  621.                             cur_time = str(datetime.fromtimestamp(int(time.time())))
  622.                             await send_message_to_users(
  623.                                 f'MARKET MAKING ALARM: {name} 15 minutes mid price delta > 5%\n{prev_time}\nprevious mid price: {price_checker_upd_p[name][1]}\n{cur_time}\ncurrent mid price: {mid_price} && ask: {book["ask_price"]} && bid: {book["bid_price"]}'
  624.                             )
  625.                             price_checker_upd_p[name][0] = int(time.time())
  626.                             price_checker_upd_p[name][1] = mid_price
  627.  
  628.                     if price_checker_upd_p[name][0] == 0 or int(time.time()) - price_checker_upd_p[name][0] >= 900: # 15 min
  629.                         price_checker_upd_p[name][0] = int(time.time())
  630.                         price_checker_upd_p[name][1] = mid_price
  631.  
  632.                     break
  633.  
  634.  
  635. # def signal_handler(sig, frame):
  636.    
  637. #     async def asyncfunc():
  638. #         await send_message_to_users('Bot was stopped by developer')
  639.  
  640. #     asyncio.run(asyncfunc())
  641. #     time.sleep(10)
  642. #     sys.exit(0)
  643.  
  644. async def main():
  645.     scheduler = AsyncIOScheduler()
  646.     scheduler.add_job(balance_checker, "interval", seconds=25, args=[bot])
  647.     scheduler.add_job(price_checker, "interval", seconds=15, args=[bot])
  648.     scheduler.add_job(volume_health_trades_checker, "interval", seconds=40, args=[bot])
  649.     scheduler.start()
  650.  
  651.     await dp.start_polling(bot)
  652.  
  653.  
  654. if __name__ == "__main__":
  655.     asyncio.run(main())
  656.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement