intelligent-trading-bot/service/server.py

158 lines
4.2 KiB
Python
Raw Permalink Normal View History

2020-12-26 17:56:54 +01:00
import os
import sys
import math, time
from datetime import datetime
from decimal import *
2021-08-31 21:13:05 +02:00
import click
2020-12-26 17:56:54 +01:00
import asyncio
2021-08-29 12:00:12 +02:00
from apscheduler.schedulers.asyncio import AsyncIOScheduler
2020-12-26 17:56:54 +01:00
2021-09-04 18:19:04 +02:00
from service.App import *
2021-09-04 21:28:45 +02:00
from common.utils import *
2021-09-04 18:19:04 +02:00
from service.collector import *
from service.analyzer import *
from service.notifier import *
from service.trader import *
2020-12-26 17:56:54 +01:00
2021-01-01 13:38:07 +01:00
import logging
log = logging.getLogger('server')
2020-12-26 17:56:54 +01:00
#
# Main procedure
#
async def main_task():
"""This task will be executed regularly according to the schedule"""
2021-08-29 19:04:58 +02:00
res = await main_collector_task()
if res:
return res
2021-08-29 18:33:49 +02:00
2021-08-29 19:04:58 +02:00
# TODO: Validation
#last_kline_ts = App.analyzer.get_last_kline_ts(symbol)
#if last_kline_ts + 60_000 != startTime:
# log.error(f"Problem during analysis. Last kline end ts {last_kline_ts + 60_000} not equal to start of current interval {startTime}.")
# Generate signals (derived features, predictions)
2021-09-04 21:28:45 +02:00
try:
analyze_task = await App.loop.run_in_executor(None, App.analyzer.analyze)
except Exception as e:
print(f"Error while analyzing data: {e}")
return
2021-08-29 19:04:58 +02:00
# Signal is stored in App.signal
2021-09-04 21:28:45 +02:00
if "notify" in App.config["actions"]:
notify_task = App.loop.create_task(notify_telegram())
2021-08-29 18:33:49 +02:00
2021-09-04 21:28:45 +02:00
# Now we have a list of signals and can make trade decisions using trading logic and trade
if "trade" in App.config["actions"]:
trade_task = App.loop.create_task(main_trader_task())
2021-08-29 19:04:58 +02:00
return
2021-08-31 21:13:05 +02:00
@click.command()
2021-09-04 18:19:04 +02:00
@click.option('--config_file', '-c', type=click.Path(), default='', help='Configuration file name')
2021-08-31 21:13:05 +02:00
def start_server(config_file):
2021-09-09 08:20:29 +02:00
load_config(config_file)
2021-08-31 21:13:05 +02:00
2021-10-23 21:51:31 +02:00
symbol = App.config["symbol"]
print(f"Initializing server. Trade pair: {symbol}. ")
2021-01-01 13:38:07 +01:00
#getcontext().prec = 8
2020-12-26 17:56:54 +01:00
#
# Validation
#
#
2021-10-23 21:51:31 +02:00
# Connect to the server and update/initialize the system state
2020-12-26 17:56:54 +01:00
#
App.client = Client(api_key=App.config["api_key"], api_secret=App.config["api_secret"])
App.analyzer = Analyzer(App.config)
2020-12-26 17:56:54 +01:00
App.loop = asyncio.get_event_loop()
# Do one time server check and state update
try:
2021-08-29 19:04:58 +02:00
App.loop.run_until_complete(data_provider_health_check())
2021-01-01 13:38:07 +01:00
except Exception as e:
print(f"Problems during health check (connectivity, server etc.) {e}")
2020-12-26 17:56:54 +01:00
if data_provider_problems_exist():
2021-01-01 13:38:07 +01:00
print(f"Problems during health check (connectivity, server etc.)")
2020-12-26 17:56:54 +01:00
return
2021-01-01 13:38:07 +01:00
print(f"Finished health check (connection, server status etc.)")
2020-12-26 17:56:54 +01:00
# Do one time data load (cold start)
2020-12-26 17:56:54 +01:00
try:
2021-08-29 19:04:58 +02:00
App.loop.run_until_complete(sync_data_collector_task())
2021-01-01 13:38:07 +01:00
except Exception as e:
print(f"Problems during initial data collection. {e}")
2020-12-26 17:56:54 +01:00
if data_provider_problems_exist():
2021-01-01 13:38:07 +01:00
print(f"Problems during initial data collection.")
2020-12-26 17:56:54 +01:00
return
2021-01-01 13:38:07 +01:00
print(f"Finished initial data collection.")
2020-12-26 17:56:54 +01:00
2021-01-01 13:38:07 +01:00
# Initialize trade status (account, balances, orders etc.)
2021-09-04 21:28:45 +02:00
if "trade" in App.config["actions"]:
try:
App.loop.run_until_complete(update_trade_status())
except Exception as e:
print(f"Problems trade status sync. {e}")
2020-12-26 17:56:54 +01:00
2021-09-04 21:28:45 +02:00
if data_provider_problems_exist():
print(f"Problems trade status sync.")
return
2020-12-26 17:56:54 +01:00
2021-09-04 21:28:45 +02:00
print(f"Finished trade status sync (account, balances etc.)")
print(f"Balance: {App.config['base_asset']} = {str(App.base_quantity)}")
print(f"Balance: {App.config['quote_asset']} = {str(App.quote_quantity)}")
2020-12-26 17:56:54 +01:00
#
# Register scheduler
2020-12-26 17:56:54 +01:00
#
App.sched = AsyncIOScheduler()
2021-01-01 13:38:07 +01:00
# logging.getLogger('apscheduler.executors.default').setLevel(logging.WARNING)
2020-12-26 17:56:54 +01:00
logging.getLogger('apscheduler').setLevel(logging.WARNING)
App.sched.add_job(
main_task,
2020-12-26 17:56:54 +01:00
trigger='cron',
2021-01-01 13:38:07 +01:00
# second='*/30',
2020-12-26 17:56:54 +01:00
minute='*',
id='main_task'
2020-12-26 17:56:54 +01:00
)
App.sched.start() # Start scheduler (essentially, start the thread)
2021-01-01 13:38:07 +01:00
print(f"Scheduler started.")
2020-12-26 17:56:54 +01:00
#
# Start event loop
#
try:
App.loop.run_forever() # Blocking. Run until stop() is called
except KeyboardInterrupt:
2021-01-01 13:38:07 +01:00
print(f"KeyboardInterrupt.")
2020-12-26 17:56:54 +01:00
finally:
App.loop.close()
2021-01-01 13:38:07 +01:00
print(f"Event loop closed.")
2020-12-26 17:56:54 +01:00
App.sched.shutdown()
2021-01-01 13:38:07 +01:00
print(f"Scheduler shutdown.")
2020-12-26 17:56:54 +01:00
return 0
2021-01-01 13:38:07 +01:00
2020-12-26 17:56:54 +01:00
if __name__ == "__main__":
2021-01-01 13:38:07 +01:00
start_server()