Compare commits

..

No commits in common. "1303ee7c5124dd3a6a9b40490613b59adc42829f" and "5c97c721ad040714cceb41b989eb15fd7bf521be" have entirely different histories.

7 changed files with 14 additions and 311 deletions

View File

@ -746,8 +746,6 @@ class broker:
order_to_send = self.exchange.create_order(pair,"market",side,amount)
time.sleep(self.wait_time)
# Wait a bit more when dealing with Kucoin
return self.get_order(order_to_send["id"],pair)
except Exception as e:
self.logger.log_this(f"Exception in new_market_order: {e}",1,pair)

View File

@ -1687,6 +1687,7 @@ def unwrapped_last_call(base,quote):
try:
if f"{base}{quote}" in broker.get_pairs():
#read_config["pairs"].remove(base+quote)
for x in running_instances:
if f"{base}/{quote}"==x.pair:
x.stop_when_profit = not x.stop_when_profit
@ -1763,7 +1764,7 @@ def unwrapped_global_last_call():
'''
try:
if broker.get_pairs!=[]:
#broker.clear_pairs()
broker.clear_pairs()
for x in running_instances:
x.stop_when_profit = True
broker.logger.log_this("Modified flag",2,f"{x.base}/{x.quote}")
@ -1909,11 +1910,11 @@ def unwrapped_toggle_autoswitch(base,quote):
if x.config_dict["autoswitch"]:
broker.logger.log_this("Autoswitch turned OFF",1,f"{base}/{quote}")
x.config_dict["autoswitch"] = False
return jsonify({"Success": "Autoswitch is now OFF"})
return jsonify({"Success": "Autoswitch it's now OFF"})
else:
broker.logger.log_this("Autoswitch turned ON",1,f"{base}/{quote}")
x.config_dict["autoswitch"] = True
return jsonify({"Success": "Autoswitch is now ON"})
return jsonify({"Success": "Autoswitch it's now ON"})
except Exception as e:
broker.logger.log_this(f"Exception while toggling autoswitch: {e}",1,f"{base}{quote}")
return jsonify({"Error": "Halp"})

View File

@ -24,6 +24,7 @@ cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours'
last_60_days_rows = cursor.fetchall()
#Last 30 days query
#cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours') AS day_utc3,
cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours') AS day_utc3,
SUM(amount) AS total_amount
FROM profits_table
@ -46,15 +47,6 @@ cursor.execute("""SELECT strftime('%Y-%m', timestamp, 'unixepoch', '-3 hours') A
ORDER BY year_month_utc3;""")
last_n_months_rows = cursor.fetchall()
#Last n months query
cursor.execute("""SELECT strftime('%Y', timestamp, 'unixepoch', '-3 hours') AS year_utc3,
SUM(amount) AS total_amount
FROM profits_table
WHERE strftime('%s', 'now') - timestamp <= 60 * 30 * 24 * 60 * 60 -- 48 months in seconds
GROUP BY year_utc3
ORDER BY year_utc3;""")
last_n_years_rows = cursor.fetchall()
#Yearly totals
cursor.execute("""SELECT strftime('%Y', timestamp, 'unixepoch', '-3 hours') AS year_utc3,
SUM(amount) AS total_amount
@ -74,13 +66,7 @@ print("Last 18 months:")
print("-"*line_width)
for row in last_n_months_rows[1:]:
print(f"{row[0]}: {round(row[1],2)}")
print("="*line_width)
print("Last 5 years:")
print("-"*line_width)
for row in last_n_years_rows:
print(f"{row[0]}: {round(row[1],2)}")
print("-"*line_width)
print(f"Last 30 days average: {round(last_30_days[0][1]/30,2)}")
print(f"Last 7 days average: {round(last_7_days[0][1]/7,2)}")
cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours') AS day_utc3,
@ -139,9 +125,6 @@ for row in by_exchange:
if row[1]=="This Month":
okex_amount = row[2]
#Close db
cursor.close()
total_amount = binance_amount+gateio_amount+kucoin_amount+okex_amount
print(f"Binance: {round(binance_amount,2)} USDT ({round(binance_amount/total_amount*100,2)}%)")

View File

@ -1,5 +1,6 @@
Mandatory:
=========
0. Mobile app.
1. Stats webpage.
2. Maintain local orderbooks for each trading pair, which enables:
2a. Smart order pricing: Prioritization of fill speed over instant profit or vice versa

View File

@ -385,8 +385,6 @@ class trader:
self.status_dict["start_time"]=self.start_time
self.status_dict["deal_start_time"]=self.deal_start_time
self.status_dict["stop_when_profit"]=self.stop_when_profit
self.status_dict["autoswitch"]=False
if "autoswitch" in self.config_dict:
self.status_dict["autoswitch"]=self.config_dict["autoswitch"]
except Exception as e:
self.broker.logger.log_this(f"Can't update status dictionary. Exception: {e}",1,self.pair)
@ -1691,8 +1689,10 @@ class trader:
if old_target-self.status_dict["quote_spent"]>0 and base_left>0 and minimum_switch_price<low_price:
low_boundary_color = bright_green
low_boundary = '{:.20f}'.format(minimum_switch_price)[:decimals].center(decimals)
if self.status_dict["price"]!=0:
multiplier = int(self.status_dict["old_long"]["tp_price"]/self.status_dict["price"])
#Logic for multiplier
#When adding a trader, this line always throws an exception since status_dict["price"] is not yet populated
percentage_to_switch = (self.status_dict["old_long"]["tp_price"]-self.status_dict["price"])*100/self.status_dict["price"]
multiplier = int(percentage_to_switch/100)+1
except Exception as e:
print(e)

View File

@ -4,7 +4,6 @@ import json
import credentials
try:
earn_api_key = credentials.get_credentials("earn_api_key")["key"]
if sys.argv[1]=="--testnet":
is_testnet = True
string_to_add = "TESTNET "
@ -26,8 +25,6 @@ except Exception as e:
headers = {'X-API-KEY': api_key}
earn_headers = {'X-API-KEY': earn_api_key}
command_list = f'''{string_to_add}COMMANDS:
INSTANCE
@ -38,14 +35,6 @@ INSTANCE
13) paused_traders 14) fetch_log 15) edit_cooldown_multiplier
16) backtests 17) get_balance
EARN
31) toggle_pause 32) get_step_size 33) set_step_size
34) get_percentage 35) set_percentage 36) get_time_between_subscriptions
37) set_time_between_subscriptions 38) get_time_between_redemptions
39) set_time_between_redemptions 40) get_minimum_amount_in_trading_account
41) set_minimum_amount_in_trading_account 42) get_last_subscription
43) get_last_redemption 44) get_total_balance
TRADERS
51) worker_status 52) get_all_worker_status
53) add_pair 54) remove_pair 55) restart_pair
@ -110,10 +99,6 @@ if __name__=="__main__":
#print("Invalid input")
#sys.exit()
port = exchanges[selection]
earn_broker = port[1:]
if earn_broker=="okex":
earn_broker="okx"
print("DCAv2 COMMANDER")
@ -147,9 +132,6 @@ if __name__=="__main__":
# break
selection = select_exchange(exchanges)
port = exchanges[selection]
earn_broker = port[1:]
if earn_broker=="okex":
earn_broker="okx"
print(f"New exchange selected: {selection}")
@ -326,128 +308,6 @@ if __name__=="__main__":
print(json.loads(requests.get(url,headers=headers).content))
input("Press ENTER to continue ")
######################
######## EARN ########
######################
elif command==31:
print("toggle_pause interrupts or resume the subcription and redemption of funds")
if input(f"This will toggle the subscription and redemption of funds on {port}. Are you sure? (Y/n) ") in ["Y","y",""]:
url = f"{base_url}/earn/toggle_pause"
parameters = {"broker": earn_broker}
print(json.loads(requests.post(url,headers=earn_headers, json=parameters).content))
input("Press ENTER to continue ")
elif command==32:
print("get_step_size returns the step size")
url = f"{base_url}/earn/get_step_size?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
elif command==33:
print("set_step_size sets the step size")
new_step_size = input("New step size? ")
if not validate_float_or_int(new_step_size):
print("Invalid step size")
break
if input(f"This will set the step size to {new_step_size}. Are you sure? (Y/n) ") in ["Y","y",""]:
url = f"{base_url}/earn/set_step_size"
parameters = {"broker": earn_broker, "new_step_size": new_step_size}
print(json.loads(requests.post(url,headers=earn_headers, json=parameters).content))
input("Press ENTER to continue ")
elif command==34:
print("get_percentage displays the percentage of funds to be allocated to earn")
url = f"{base_url}/earn/get_percentage?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
elif command==35:
print("set_percentage sets the percentage of funds to be allocated to earn")
new_percentage = input("New percentage? ")
if not validate_float_or_int(new_percentage):
print("Invalid percentage")
break
if input(f"This will set the percentage to {new_percentage}. Are you sure? (Y/n) ") in ["Y","y",""]:
url = f"{base_url}/earn/set_percentage"
parameters = {"broker": earn_broker, "new_percentage": new_percentage}
print(json.loads(requests.post(url,headers=earn_headers, json=parameters).content))
input("Press ENTER to continue ")
elif command==36:
print("get_time_between_subscriptions displays the time to wait between subscriptions")
url = f"{base_url}/earn/get_time_between_subscriptions?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
elif command==37:
print("set_time_between_subscriptions sets the time to wait between subscriptions")
new_time_between_subscriptions = input("New time between subscriptions? ")
if not validate_int(new_time_between_subscriptions):
print("Invalid time")
break
if input(f"This will set the time to wait between subscriptions to {new_time_between_subscriptions}. Are you sure? (Y/n) ") in ["Y","y",""]:
url = f"{base_url}/earn/set_time_between_subscriptions"
parameters = {"broker": earn_broker, "new_time_between_subscriptions": new_time_between_subscriptions}
print(json.loads(requests.post(url,headers=earn_headers, json=parameters).content))
input("Press ENTER to continue ")
elif command==38:
print("get_time_between_redemptions displays the time to wait between redemptions")
url = f"{base_url}/earn/get_time_between_redemptions?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
elif command==39:
print("set_time_between_redemptions sets the time to wait between redemptions")
new_time_between_redemptions = input("New time between redemptions? ")
if not validate_int(new_time_between_redemptions):
print("Invalid time")
break
if input(f"This will set the time to wait between redemptions to {new_time_between_redemptions}. Are you sure? (Y/n) ") in ["Y","y",""]:
url = f"{base_url}/earn/set_time_between_redemptions"
parameters = {"broker": earn_broker, "new_time_between_redemptions": new_time_between_redemptions}
print(json.loads(requests.post(url,headers=earn_headers, json=parameters).content))
input("Press ENTER to continue ")
elif command==40:
print("get_minimum_amount_in_trading_account displays the minimum amount of funds that always have to exist in the trading account")
url = f"{base_url}/earn/get_minimum_amount_in_trading_account?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
elif command==41:
print("set_minimum_amount_in_trading_account sets the minimum amount of funds that always have to exist in the trading account")
new_minimum_amount_in_trading_account = input("New minimum amount in trading account? ")
if not validate_int(new_minimum_amount_in_trading_account):
print("Invalid amount")
break
if input(f"This will set the minimum amount of funds that always have to exist in the trading account to {new_minimum_amount_in_trading_account}. Are you sure? (Y/n) ") in ["Y","y",""]:
url = f"{base_url}/earn/set_minimum_amount_in_trading_account"
parameters = {"broker": earn_broker, "new_minimum_amount_in_trading_account": new_minimum_amount_in_trading_account}
print(json.loads(requests.post(url,headers=earn_headers, json=parameters).content))
input("Press ENTER to continue ")
elif command==42:
print("get_last_subscription display the last subscription")
url = f"{base_url}/earn/get_last_subscription?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
elif command==43:
print("get_last_redemptions displays the last redemption")
url = f"{base_url}/earn/get_last_redemption?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
elif command==44:
print("get_total_balance displays the trading account balance and the earning account balance")
url = f"{base_url}/earn/get_total_balance?broker={earn_broker}"
print(json.loads(requests.get(url,headers=earn_headers).content))
input("Press ENTER to continue ")
######################
####### TRADER #######
######################

View File

@ -4,7 +4,6 @@ import datetime
import time
import ccxt
import credentials
import calendar
import requests
import logging
from flask import Flask, jsonify, request
@ -60,126 +59,6 @@ def load_keys_from_db(file_name):
return valid_keys
def profit_report():
##Queries
connection = sqlite3.connect(profits_database)
cursor = connection.cursor()
#Last 60 days query
cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours') AS day_utc3,
SUM(amount) AS total_amount
FROM profits_table
WHERE strftime('%s', 'now') - timestamp <= 60 * 24 * 60 * 60 -- 60 days in seconds
GROUP BY day_utc3
ORDER BY day_utc3;""")
last_60_days_rows = cursor.fetchall()
#Last 30 days query
#cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours') AS day_utc3,
cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours') AS day_utc3,
SUM(amount) AS total_amount
FROM profits_table
WHERE strftime('%s', 'now') - timestamp <= 30 * 24 * 60 * 60 -- 30 days in seconds;""")
last_30_days = cursor.fetchall()
#Last 7 days query
cursor.execute("""SELECT strftime('%Y-%m-%d', timestamp, 'unixepoch', '-3 hours') AS day_utc3,
SUM(amount) AS total_amount
FROM profits_table
WHERE strftime('%s', 'now') - timestamp <= 7 * 24 * 60 * 60 -- 7 days in seconds;""")
last_7_days = cursor.fetchall()
#Last n months query
cursor.execute("""SELECT strftime('%Y-%m', timestamp, 'unixepoch', '-3 hours') AS year_month_utc3,
SUM(amount) AS total_amount
FROM profits_table
WHERE strftime('%s', 'now') - timestamp <= 18 * 30 * 24 * 60 * 60 -- 18 months in seconds
GROUP BY year_month_utc3
ORDER BY year_month_utc3;""")
last_n_months_rows = cursor.fetchall()
#Yearly totals
cursor.execute("""SELECT strftime('%Y', timestamp, 'unixepoch', '-3 hours') AS year_utc3,
SUM(amount) AS total_amount
FROM profits_table
WHERE strftime('%s', 'now') - timestamp <= 24 * 365 * 60 * 60 -- 365 days in seconds
GROUP BY year_utc3
ORDER BY year_utc3;""")
yearly_totals = cursor.fetchall()
#Per exchange
cursor.execute("""SELECT
exchange_name,
CASE
WHEN strftime('%Y-%m', timestamp, 'unixepoch', '-3 hours') = strftime('%Y-%m', 'now', 'localtime') THEN 'This Month'
WHEN strftime('%Y-%m', timestamp, 'unixepoch', '-3 hours') = strftime('%Y-%m', 'now', 'localtime', '-1 month') THEN 'Last Month'
ELSE 'Other Months'
END AS month_group,
SUM(amount) AS total_amount
FROM
profits_table
WHERE
strftime('%s', 'now') - timestamp <= 60 * 24 * 60 * 60 -- 60 days in seconds
GROUP BY
exchange_name, month_group
ORDER BY
exchange_name, month_group;""")
per_exchange = cursor.fetchall()
#Close db
cursor.close()
#Projection calculation
days_in_month = calendar.monthrange(datetime.date.today().year, datetime.date.today().month)[1]
daily_combined_media = (last_30_days[0][1]/30+last_7_days[0][1]/7)/2
current_amount = last_n_months_rows[-1][1]
days_past_this_month = int(last_60_days_rows[-1][0][8:10])
#Per exchange
binance_amount = 0
gateio_amount = 0
kucoin_amount = 0
okex_amount = 0
for row in per_exchange:
if row[0]=="binance":
if row[1]=="This Month":
binance_amount = row[2]
elif row[0]=="gateio":
if row[1]=="This Month":
gateio_amount = row[2]
elif row[0]=="kucoin":
if row[1]=="This Month":
kucoin_amount = row[2]
elif row[0]=="okex":
if row[1]=="This Month":
okex_amount = row[2]
total_amount = binance_amount+gateio_amount+kucoin_amount+okex_amount
last_60_days_result = {row[0]: round(row[1],2) for row in last_60_days_rows}
last_18_months_result = {row[0]: round(row[1],2) for row in last_n_months_rows}
last_30_days_average = last_30_days[0][1]/30
last_7_days_average = last_7_days[0][1]/7
this_month_projection = current_amount + daily_combined_media*(days_in_month-days_past_this_month)
binance_percentage = binance_amount/total_amount*100
gateio_percentage = gateio_amount/total_amount*100
kucoin_percentage = kucoin_amount/total_amount*100
okex_percentage = okex_amount/total_amount*100
return {"Last 60 days": last_60_days_result,
"Last 18 months": last_18_months_result,
"Last 30 days average": last_30_days_average,
"Last 7 days average": last_7_days_average,
"This month projection": this_month_projection,
"Binance": binance_amount,
"Binance percentage": binance_percentage,
"Gateio": gateio_amount,
"Gateio percentage": gateio_percentage,
"Kucoin": kucoin_amount,
"Kucoin percentage": kucoin_percentage,
"OKX": okex_amount,
"OKX percentage": okex_percentage,
"Total profit": total_amount}
def query_total_profit(pair=None):
'''
Returns total profit of the trading pair.
@ -441,23 +320,6 @@ def fetch_backtests():
return jsonify({'Error': 'API key invalid'}), 401
@stats_api.route("/fetch_profit_report")
def fetch_profit_report():
'''
GET request
Parameters: None
Returns: JSON object with profit report data
'''
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
try:
return jsonify(profit_report())
except Exception as e:
print(e)
return jsonify({"Error": f"{e}"})
return jsonify({'Error': 'API key invalid'}), 401
@stats_api.route("/clear_caches")
def clear_hashes():
global hashes_db
@ -533,8 +395,6 @@ def fetch_full_log():
'''
GET request
Parameters: 'exchange_name" -> string
It trims the full log to 200 lines, to avoid sending too much data to the client.
'''
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
try:
@ -542,11 +402,11 @@ def fetch_full_log():
width = 0
last_lines,amount_of_lines = last_n_lines(f"../logs/{exchange_name}.log",width,0,full_log=True)
if not cache_requests:
return jsonify({"line": last_lines[-200:], "amount_of_lines": amount_of_lines})
return jsonify({"line": last_lines, "amount_of_lines": amount_of_lines})
response_hash = hash(str({"line": last_lines, "amount_of_lines": amount_of_lines}))
if hashes_db["fetch_full_log"]!=response_hash:
hashes_db["fetch_full_log"] = response_hash
return jsonify({"line": last_lines[-200:], "amount_of_lines": amount_of_lines})
return jsonify({"line": last_lines, "amount_of_lines": amount_of_lines})
return jsonify({"no_changes": True})
except Exception as e:
print(e)