2022-03-20 10:09:33 +01:00
from pathlib import Path
from typing import Union
import json
2022-06-26 17:32:41 +02:00
import pandas as pd
2022-03-20 10:09:33 +01:00
PACKAGE_ROOT = Path ( __file__ ) . parent . parent
#PACKAGE_PARENT = '..'
#SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
#sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
#PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__))
class App :
""" Globally visible variables. """
# System
loop = None # asyncio main loop
sched = None # Scheduler
analyzer = None # Store and analyze data
# Connector client
client = None
# WebSocket for push notifications
bm = None
conn_key = None # Socket
signal = None , # Latest signal "BUY", "SELL"
#
# State of the server (updated after each interval)
#
# State 0 or None or empty means ok. String and other non empty objects mean error
error_status = 0 # Networks, connections, exceptions etc. what does not allow us to work at all
server_status = 0 # If server allow us to trade (maintenance, down etc.)
account_status = 0 # If account allows us to trade (funds, suspended etc.)
trade_state_status = 0 # Something wrong with our trading logic (wrong use, inconsistent state etc. what we cannot recover)
# Trade status
2022-04-10 19:38:53 +02:00
transaction = None
2022-03-20 10:09:33 +01:00
status = None # BOUGHT, SOLD, BUYING, SELLING
order = None # Latest or current order
order_time = None # Order submission time
# Available assets for trade
# Can be set by the sync/recover function or updated by the trading algorithm
base_quantity = " 0.04108219 " # BTC owned (on account, already bought, available for trade)
quote_quantity = " 1000.0 " # USDT owned (on account, available for trade)
#
# Trader. Status data retrieved from the server. Below are examples only.
#
system_status = { " status " : 0 , " msg " : " normal " } # 0: normal,1:system maintenance
2022-04-18 13:25:25 +02:00
symbol_info = { }
account_info = { }
2022-03-20 10:09:33 +01:00
#
# Constant configuration parameters
#
config = {
" actions " : [ " notify " ] , # Values: notify, trade
# Binance
" api_key " : " " ,
" api_secret " : " " ,
# Telegram
" telegram_bot_token " : " " , # Source address of messages
" telegram_chat_id " : " " , # Destination address of messages
2022-04-17 19:55:22 +02:00
# File locations
" data_folder " : " " , # It is needed for model training
# Symbol determines sub-folder and used in other identifiers
2022-04-02 11:50:07 +02:00
" symbol " : " " , # BTCUSDT ETHUSDT
2022-04-19 19:05:39 +02:00
# It will be appended to generated file names and denotes config (like config name).
2022-04-23 09:18:45 +02:00
# TODO: In future, we could/should change it semantics, and store the generated files in the folder with this name, rather than append a modifier to file names
2022-04-19 19:05:39 +02:00
" config_file_modifier " : " " ,
2022-03-20 10:09:33 +01:00
2022-04-15 21:45:46 +02:00
# File name conventions
2022-04-17 19:55:22 +02:00
" merge_file_modifier " : " data " ,
2022-04-15 21:45:46 +02:00
" feature_file_modifier " : " features " ,
" matrix_file_modifier " : " matrix " ,
2022-06-26 17:32:41 +02:00
" predict_file_modifier " : " predictions " , # predict, predict-rolling
2022-04-15 21:45:46 +02:00
" signal_file_modifier " : " performance " ,
2022-04-23 09:18:45 +02:00
# =====================================
# === MERGER and (online) COLLECTOR ===
2022-04-17 19:55:22 +02:00
# Specify which data sources to merge into one file with all source columns
# Format: (folder, file, prefix) - (symbol, data source, column prefix)
2022-04-23 09:18:45 +02:00
# These descriptors are also used to retrieve data by collector in online mode - folder name is symbol name
2022-04-17 19:55:22 +02:00
#"data_sources": [
# {"folder": "BTCUSDT", "file": "klines", "column_prefix": ""},
#],
2022-04-24 20:52:38 +02:00
#"data_sources": [
# {"folder": "BTCUSDT", "file": "klines", "column_prefix": "btc"},
# {"folder": "ETHUSDT", "file": "klines", "column_prefix": "eth"},
#],
2022-04-17 19:55:22 +02:00
2022-04-15 11:46:19 +02:00
# ==========================
2022-04-02 11:50:07 +02:00
# === FEATURE GENERATION ===
2022-03-20 10:09:33 +01:00
2022-04-19 19:05:39 +02:00
# What columns to pass to which feature generator and how to prefix its derived features
2022-04-18 13:25:25 +02:00
" feature_sets " : [
2022-04-24 20:52:38 +02:00
{ " column_prefix " : " btc " , " generator " : " klines " , " feature_prefix " : " btc " } ,
2022-04-23 09:18:45 +02:00
{ " column_prefix " : " eth " , " generator " : " klines " , " feature_prefix " : " eth " } ,
2022-04-18 13:25:25 +02:00
] ,
# Parameters of klines feature generator
2022-04-02 11:50:07 +02:00
# If these are changed, then feature names (below) will also have to be changed
2022-06-26 17:32:41 +02:00
#"base_window_kline": 40320, # 4 weeks
#"windows_kline": [1, 20, 60, 360, 1440, 10080],
#"area_windows_kline": [20, 60, 360, 1440, 10080],
#"base_window_kline": 20160, # 2 weeks
#"windows_kline": [1, 20, 60, 180, 720, 2880],
#"area_windows_kline": [60, 120, 180, 720, 2880],
#"windows_kline": [1, 30, 120, 360, 1440, 4320],
#"area_windows_kline": [30, 120, 360, 1440, 4320],
#"windows_kline": [1, 60, 180, 720, 2880, 5760],
#"area_windows_kline": [60, 180, 720, 2880, 5760],
" base_window_kline " : 10080 , # 1 week
" windows_kline " : [ 1 , 10 , 30 , 180 , 720 , 1440 ] ,
" area_windows_kline " : [ 10 , 30 , 180 , 720 , 1440 ] ,
2022-04-02 11:50:07 +02:00
2022-04-19 19:05:39 +02:00
# ========================
# === LABEL GENERATION ===
" high_low_horizon " : 1440 , # Parameter of labels: computing max and min for this horizon ahead
2022-04-24 20:52:38 +02:00
" top_bot_column_name " : " close " ,
2022-04-19 19:05:39 +02:00
# ===========================
# === MODEL TRAIN/PREDICT ===
# off-line and on-line
# Minimum history required to compute derived features
# It is used in online mode where we need to maintain data window of this size or larger
2022-04-02 11:50:07 +02:00
# Take maximum aggregation windows from feature generation code (and add something to be sure that we have all what is needed)
# Basically, should be equal to base_window_kline
2022-06-26 17:32:41 +02:00
" features_horizon " : 10180 ,
2022-04-02 11:50:07 +02:00
2022-04-19 19:05:39 +02:00
# One model is for each (label, train_features, algorithm)
# Feature column names returned by the klines feature generator
# They are used by train/predict
2022-04-02 11:50:07 +02:00
" features_kline " : [
2022-06-26 17:32:41 +02:00
' btc_close_1 ' , ' btc_close_10 ' , ' btc_close_30 ' , ' btc_close_180 ' , ' btc_close_720 ' , ' btc_close_1440 ' ,
' btc_close_std_10 ' , ' btc_close_std_30 ' , ' btc_close_std_180 ' , ' btc_close_std_720 ' , ' btc_close_std_1440 ' ,
' btc_volume_1 ' , ' btc_volume_10 ' , ' btc_volume_30 ' , ' btc_volume_180 ' , ' btc_volume_720 ' , ' btc_volume_1440 ' ,
' btc_span_1 ' , ' btc_span_10 ' , ' btc_span_30 ' , ' btc_span_180 ' , ' btc_span_720 ' , ' btc_span_1440 ' ,
' btc_trades_1 ' , ' btc_trades_10 ' , ' btc_trades_30 ' , ' btc_trades_180 ' , ' btc_trades_720 ' , ' btc_trades_1440 ' ,
' btc_tb_base_1 ' , ' btc_tb_base_10 ' , ' btc_tb_base_30 ' , ' btc_tb_base_180 ' , ' btc_tb_base_720 ' , ' btc_tb_base_1440 ' ,
#'btc_close_area_10', 'btc_close_area_30', 'btc_close_area_180', 'btc_close_area_720', 'btc_close_area_1440',
' btc_close_trend_10 ' , ' btc_close_trend_30 ' , ' btc_close_trend_180 ' , ' btc_close_trend_720 ' , ' btc_close_trend_1440 ' ,
' btc_volume_trend_10 ' , ' btc_volume_trend_30 ' , ' btc_volume_trend_180 ' , ' btc_volume_trend_720 ' , ' btc_volume_trend_1440 ' ,
' eth_close_1 ' , ' eth_close_10 ' , ' eth_close_30 ' , ' eth_close_180 ' , ' eth_close_720 ' , ' eth_close_1440 ' ,
' eth_close_std_10 ' , ' eth_close_std_30 ' , ' eth_close_std_180 ' , ' eth_close_std_720 ' , ' eth_close_std_1440 ' ,
' eth_volume_1 ' , ' eth_volume_10 ' , ' eth_volume_30 ' , ' eth_volume_180 ' , ' eth_volume_720 ' , ' eth_volume_1440 ' ,
' eth_span_1 ' , ' eth_span_10 ' , ' eth_span_30 ' , ' eth_span_180 ' , ' eth_span_720 ' , ' eth_span_1440 ' ,
' eth_trades_1 ' , ' eth_trades_10 ' , ' eth_trades_30 ' , ' eth_trades_180 ' , ' eth_trades_720 ' , ' eth_trades_1440 ' ,
' eth_tb_base_1 ' , ' eth_tb_base_10 ' , ' eth_tb_base_30 ' , ' eth_tb_base_180 ' , ' eth_tb_base_720 ' , ' eth_tb_base_1440 ' ,
#'eth_close_area_10', 'eth_close_area_30', 'eth_close_area_180', 'eth_close_area_720', 'eth_close_area_1440',
' eth_close_trend_10 ' , ' eth_close_trend_30 ' , ' eth_close_trend_180 ' , ' eth_close_trend_720 ' , ' eth_close_trend_1440 ' ,
' eth_volume_trend_10 ' , ' eth_volume_trend_30 ' , ' eth_volume_trend_180 ' , ' eth_volume_trend_720 ' , ' eth_volume_trend_1440 '
2022-04-02 11:50:07 +02:00
] ,
2022-04-23 09:18:45 +02:00
# Used to select columns for training by adding together different feature sets (the lists are defined elswhere in variables like "features_kline")
" train_features " : [ " kline " ] ,
# algorithm descriptors from model store
" algorithms " : [ " nn " ] , # gb, nn, lc - definitions of their parameters are in model store
2022-04-16 18:22:55 +02:00
2022-04-16 20:30:34 +02:00
# This will be excluded from model training
" label_horizon " : 0 ,
2022-04-19 19:05:39 +02:00
# These labels are specified manually and are produced by label generator
2022-04-02 11:50:07 +02:00
# Models will be trained for these models
2022-03-20 10:09:33 +01:00
" labels " : [
2022-04-23 09:18:45 +02:00
" bot2_025 " , " bot2_05 " , " bot2_075 " , " bot2_1 " , " bot2_125 " , " bot2_15 " ,
" top2_025 " , " top2_05 " , " top2_075 " , " top2_1 " , " top2_125 " , " top2_15 " ,
2022-04-24 20:52:38 +02:00
] ,
" _labels " : [
2022-04-23 09:18:45 +02:00
" bot3_025 " , " bot3_05 " , " bot3_075 " , " bot3_1 " , " bot3_125 " , " bot3_15 " , " bot3_175 " ,
" top3_025 " , " top3_05 " , " top3_075 " , " top3_1 " , " top3_125 " , " top3_15 " , " top3_175 " ,
2022-04-19 19:05:39 +02:00
2022-04-23 09:18:45 +02:00
" bot4_025 " , " bot4_05 " , " bot4_075 " , " bot4_1 " , " bot4_125 " , " bot4_15 " , " bot4_175 " , " bot4_2 " ,
" top4_025 " , " top4_05 " , " top4_075 " , " top4_1 " , " top4_125 " , " top4_15 " , " top4_175 " , " top4_2 " ,
2022-04-19 19:05:39 +02:00
2022-04-23 09:18:45 +02:00
" bot5_025 " , " bot5_05 " , " bot5_075 " , " bot5_1 " , " bot5_125 " , " bot5_15 " , " bot5_175 " , " bot5_2 " , " bot5_25 " ,
" top5_025 " , " top5_05 " , " top5_075 " , " top5_1 " , " top5_125 " , " top5_15 " , " top5_175 " , " top5_2 " , " top5_25 " ,
2022-04-10 19:38:53 +02:00
2022-03-20 10:09:33 +01:00
' high_max_180 ' , # Maximum high (relative)
2022-04-15 11:46:19 +02:00
" high_10 " , " high_15 " , " high_20 " , " high_25 " , " high_30 " ,
" low_10 " , " low_15 " , " low_20 " , " low_25 " , " low_30 " ,
2022-03-20 10:09:33 +01:00
' low_min_180 ' , # Minimum low (relative)
' low_01 ' , ' low_02 ' , ' low_03 ' , ' low_04 ' , # Always above
' low_10 ' , ' low_15 ' , ' low_20 ' , ' low_25 ' , # At least one time below
' high_to_low_180 ' ,
2022-04-02 11:50:07 +02:00
' close_area_future_60 ' , ' close_area_future_120 ' , ' close_area_future_180 ' , ' close_area_future_300 ' ,
] ,
2022-03-20 10:09:33 +01:00
2022-04-16 18:22:55 +02:00
# =========================
# === SIGNAL GENERATION ===
2022-03-25 22:49:33 +01:00
2022-04-18 13:25:25 +02:00
# These are predicted columns <label, train_features, algorithm> as well as model (pair) names
2022-04-24 20:52:38 +02:00
" buy_labels " : [ ] ,
" sell_labels " : [ ] ,
2022-04-13 16:34:38 +02:00
" _buy_labels " : [ " bot4_1_k_lc " , " bot4_15_k_lc " , " bot4_2_k_lc " , " bot4_25_k_lc " , " bot4_3_k_lc " ] ,
" _sell_labels " : [ " top4_1_k_lc " , " top4_15_k_lc " , " top4_2_k_lc " , " top4_25_k_lc " , " top4_3_k_lc " ] ,
2022-03-20 10:09:33 +01:00
2022-03-25 22:49:33 +01:00
# It defines how signal scores, trade signals, and notification signals will be generated
# from point-wise prediction scores for two groups of labels
" signal_model " : {
# First, aggregation in group over various algorithms and label parameters
2022-03-26 12:43:02 +01:00
" buy_point_threshold " : None , # Second, produce boolean column (optional)
2022-04-10 19:38:53 +02:00
" buy_window " : 3 , # Third, aggregate in time
2022-03-25 22:49:33 +01:00
# Now we have the final score
2022-04-13 16:34:38 +02:00
" buy_signal_threshold " : 0.65 , # To decide whether to buy/sell after all aggregations/combinations
2022-04-10 19:38:53 +02:00
" buy_notify_threshold " : 0.05 , # To decide whether to notify (can be an option of individual users/consumers)
2022-03-25 22:49:33 +01:00
" combine " : " " , # "no_combine", "relative", "difference" Find relative/difference
2022-03-26 12:43:02 +01:00
" sell_point_threshold " : None ,
2022-04-13 16:34:38 +02:00
" sell_window " : 3 ,
" sell_signal_threshold " : 0.65 ,
2022-04-19 19:05:39 +02:00
" sell_notify_threshold " : 0.05 ,
2022-03-25 22:49:33 +01:00
2022-04-13 16:34:38 +02:00
" trade_icon_step " : 0.1 , # For each step, one icon added
" notify_frequency_minutes " : 10 , # 1m, 5m, 10m, 15m etc. Minutes will be divided by this number
2022-03-20 10:09:33 +01:00
} ,
2022-04-15 11:46:19 +02:00
# =====================
2022-03-20 10:09:33 +01:00
# === TRADER SERVER ===
2022-04-19 19:05:39 +02:00
" base_asset " : " " , # BTC ETH
" quote_asset " : " " ,
2022-03-20 10:09:33 +01:00
" trader " : {
# For debugging: determine what parts of code will be executed
" no_trades_only_data_processing " : False , # in market or out of market processing is excluded (all below parameters ignored)
" test_order_before_submit " : False , # Send test submit to the server as part of validation
" simulate_order_execution " : False , # Instead of real orders, simulate their execution (immediate buy/sell market orders and use high price of klines for limit orders)
" percentage_used_for_trade " : 99 , # in % to the available USDT quantity, that is, we will derive how much BTC to buy using this percentage
" limit_price_adjustment " : - 0.0001 , # Limit price of orders will be better than the latest close price (0 means no change, positive - better for us, negative - worse for us)
# Signal model (trade strategy) - currently NOT USED
" sell_timeout " : 70 , # Seconds
" percentage_sell_price " : 1.018 , # our planned profit per trade via limit sell order (part of the model)
} ,
2022-04-15 11:46:19 +02:00
# ==================
2022-03-20 10:09:33 +01:00
# === COLLECTORS ===
" collector " : {
" folder " : " DATA " ,
" flush_period " : 300 , # seconds
" depth " : {
" folder " : " DEPTH " ,
" symbols " : [ " BTCUSDT " , " ETHBTC " , " ETHUSDT " , " IOTAUSDT " , " IOTABTC " , " IOTAETH " ] ,
" limit " : 100 , # Legal values (depth): '5, 10, 20, 50, 100, 500, 1000, 5000' <100 weight=1
" freq " : " 1m " , # Binance standard frequency: 5s, 1m etc.
} ,
" stream " : {
" folder " : " STREAM " ,
# Stream formats:
# For kline channel: <symbol>@kline_<interval>, Event type: "e": "kline", Symbol: "s": "BNBBTC"
# For depth channel: <symbol>@depth<levels>[@100ms], Event type: NO, Symbol: NO
# btcusdt@ticker
" channels " : [ " kline_1m " , " depth20 " ] , # kline_1m, depth20, depth5
" symbols " : [ " BTCUSDT " , " ETHBTC " , " ETHUSDT " , " IOTAUSDT " , " IOTABTC " , " IOTAETH " ] ,
# "BTCUSDT", "ETHBTC", "ETHUSDT", "IOTAUSDT", "IOTABTC", "IOTAETH"
}
} ,
}
def data_provider_problems_exist ( ) :
if App . error_status != 0 :
return True
if App . server_status != 0 :
return True
return False
def problems_exist ( ) :
if App . error_status != 0 :
return True
if App . server_status != 0 :
return True
if App . account_status != 0 :
return True
if App . trade_state_status != 0 :
return True
return False
def load_config ( config_file ) :
if config_file :
config_file_path = PACKAGE_ROOT / config_file
with open ( config_file_path ) as json_file :
config_json = json . load ( json_file )
App . config . update ( config_json )
if __name__ == " __main__ " :
pass