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 | | |
|
2021-08-29 14:22:12 +02:00 | | | import asyncio
|
2021-08-29 12:00:12 +02:00 | | |
|
2021-08-29 13:17:22 +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
|
| | | #
|
| | |
|
2021-08-29 13:17:22 +02:00 | | | 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 13:17:22 +02:00 | | |
|
2021-08-29 19:04:58 +02:00 | | | return
|
| | |
|
2021-08-29 13:17:22 +02:00 | | |
|
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"])
|
| | |
|
2021-10-09 19:47:49 +02:00 | | | 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 | | |
|
2021-10-09 19:47:49 +02: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.)")
|
2021-10-09 19:47:49 +02:00 | | | 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 | | |
|
| | | #
|
2021-08-29 13:17:22 +02:00 | | | # Register scheduler
|
2020-12-26 17:56:54 +01:00 | | | #
|
| | |
|
2021-08-29 13:17:22 +02: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(
|
2021-08-29 13:17:22 +02:00 | | | 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='*',
|
2021-08-29 13:17:22 +02:00 | | | 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()
|