more work
This commit is contained in:
parent
ef99063dae
commit
5e7ab5a09d
|
|
@ -4,3 +4,4 @@ libraries/wrappers/__pycache__/*
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
credentials.py
|
credentials.py
|
||||||
|
some_tests.py
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
def balance_accounts(spot_balance, earn_balance, lower_limit, step_size, percentage):
|
def balance_accounts(spot_balance, earn_balance, lower_limit, step_size, percentage):
|
||||||
target_spot_balance = (spot_balance + earn_balance) * percentage
|
spot_balance+=earn_balance
|
||||||
|
earn_balance=0
|
||||||
|
|
||||||
|
#target_spot_balance = (spot_balance + earn_balance) * percentage
|
||||||
|
target_spot_balance = spot_balance * percentage
|
||||||
|
|
||||||
while abs(spot_balance - target_spot_balance) >= step_size:
|
while abs(spot_balance - target_spot_balance) >= step_size:
|
||||||
if spot_balance < target_spot_balance:
|
if spot_balance < target_spot_balance:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
import time
|
||||||
|
from libraries.balance_accounts import balance_accounts
|
||||||
|
|
||||||
|
|
||||||
|
class earner:
|
||||||
|
def __init__(self, connector, config):
|
||||||
|
self.connector = connector
|
||||||
|
self.currency = config["currency"]
|
||||||
|
self.minimum_amount_in_trading_account = config["minimum_amount_in_trading_account"]
|
||||||
|
self.step_size = config["step_size"]
|
||||||
|
self.percentage = config["percentage"]
|
||||||
|
self.time_between_subscriptions = config["time_between_subscriptions"]
|
||||||
|
self.time_between_redemptions = config["time_between_redemptions"]
|
||||||
|
|
||||||
|
self.last_subscription_time = 0
|
||||||
|
self.last_redemption_time = 0
|
||||||
|
self.start_time = time.time()
|
||||||
|
|
||||||
|
self.trading_balance = 0
|
||||||
|
self.earning_balance = 0
|
||||||
|
|
||||||
|
self.status_string = ""
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.connector)
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_subscription(self):
|
||||||
|
return {str(self.connector): self.last_subscription_time}
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_redemption(self):
|
||||||
|
return {str(self.connector): self.last_redemption_time}
|
||||||
|
|
||||||
|
|
||||||
|
def get_status_string(self):
|
||||||
|
return self.status_string
|
||||||
|
|
||||||
|
|
||||||
|
def get_trading_balance(self):
|
||||||
|
return float(self.trading_balance)
|
||||||
|
|
||||||
|
|
||||||
|
def get_earning_balance(self):
|
||||||
|
return float(self.earning_balance)
|
||||||
|
|
||||||
|
|
||||||
|
def subscribe(self,amount):
|
||||||
|
print(f"{str(self.connector)} | Subscribing {amount} {self.currency}")
|
||||||
|
|
||||||
|
if True:
|
||||||
|
self.last_subscription_time = time.time()
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def redeem(self,amount):
|
||||||
|
print(f"{str(self.connector)} | Redeeming {amount} {self.currency}")
|
||||||
|
if True:
|
||||||
|
self.last_redemption_time = time.time()
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
'''
|
||||||
|
1. Get trading and earning balances
|
||||||
|
2. Call balance_accounts
|
||||||
|
3. If there are differences:
|
||||||
|
a. If subscribe side, subscribe if time_since_last_subscription>time_between_subscriptions
|
||||||
|
b. If redeem side, redeem if time_since_last_redeem>time_between_redemptions
|
||||||
|
4. Output status to status_string
|
||||||
|
'''
|
||||||
|
|
||||||
|
#Get trading and earning balances
|
||||||
|
trading_balance_dict = self.connector.get_trading_balance(self.currency)
|
||||||
|
if "Error" not in trading_balance_dict:
|
||||||
|
self.trading_balance = trading_balance_dict[self.currency]
|
||||||
|
else:
|
||||||
|
self.trading_balance = None
|
||||||
|
|
||||||
|
earning_balance_dict = self.connector.get_position(self.currency)
|
||||||
|
if earning_balance_dict=={}:
|
||||||
|
self.earning_balance = 0
|
||||||
|
elif "Error" not in earning_balance_dict:
|
||||||
|
self.earning_balance = earning_balance_dict["amount"]
|
||||||
|
else:
|
||||||
|
self.earning_balance = None
|
||||||
|
|
||||||
|
#Call balance_accounts
|
||||||
|
target_trading_amount, target_earning_amount = balance_accounts(float(self.trading_balance),
|
||||||
|
float(self.earning_balance),
|
||||||
|
self.minimum_amount_in_trading_account,
|
||||||
|
self.step_size,
|
||||||
|
self.percentage)
|
||||||
|
|
||||||
|
#Check difference
|
||||||
|
earning_delta = 0
|
||||||
|
if self.earning_balance is None:
|
||||||
|
print(f"{str(self.connector)} - There was an error fetching earning balance")
|
||||||
|
else:
|
||||||
|
if float(self.earning_balance)!=0:
|
||||||
|
earning_delta = target_earning_amount - float(self.earning_balance)
|
||||||
|
if earning_delta>self.step_size and time.time()-self.last_subscription_time>self.time_between_subscriptions:
|
||||||
|
self.subscribe(earning_delta)
|
||||||
|
if earning_delta<-self.step_size and time.time()-self.last_redemption_time>self.time_between_redemptions:
|
||||||
|
self.redeem(-earning_delta)
|
||||||
|
print(f"Difference: {earning_delta}")
|
||||||
|
|
||||||
|
|
||||||
|
#Output status to status_string
|
||||||
|
balances_string = f"Trading balance: {float(self.trading_balance):.2f} {self.currency} | Earning balance: {float(self.earning_balance):.2f} {self.currency}"
|
||||||
|
percentages_string = f"On earn: {float(self.earning_balance)/float(self.trading_balance):.2%}"
|
||||||
|
|
||||||
|
self.status_string = f"{self} | {balances_string} | {percentages_string}"
|
||||||
|
|
||||||
|
|
@ -27,6 +27,7 @@ class binance_earn:
|
||||||
for item in account["balances"]:
|
for item in account["balances"]:
|
||||||
if item["asset"]==coin:
|
if item["asset"]==coin:
|
||||||
return {coin: item["free"]}
|
return {coin: item["free"]}
|
||||||
|
return {"Error": "Coin not found"}
|
||||||
|
|
||||||
|
|
||||||
def get_available_products(self, coin):
|
def get_available_products(self, coin):
|
||||||
|
|
|
||||||
75
main.py
75
main.py
|
|
@ -3,32 +3,39 @@ from libraries.wrappers import earn_binance
|
||||||
from libraries.wrappers import earn_kucoin
|
from libraries.wrappers import earn_kucoin
|
||||||
from libraries.wrappers import earn_okx
|
from libraries.wrappers import earn_okx
|
||||||
from libraries.wrappers import earn_gateio
|
from libraries.wrappers import earn_gateio
|
||||||
|
from libraries.earner import earner
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import time
|
import time
|
||||||
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
class earner:
|
|
||||||
def __init__(self, connector, config):
|
|
||||||
self.connector = connector
|
|
||||||
self.currency = config["currency"]
|
|
||||||
self.minimum_amount_in_trading_account = config["minimum_amount_in_trading_account"]
|
|
||||||
self.step_size = config["step_size"]
|
|
||||||
self.percentage = config["percentage"]
|
|
||||||
self.time_between_subscriptions = config["time_between_subscriptions"]
|
|
||||||
self.time_between_redemptions = config["time_between_redemptions"]
|
|
||||||
|
|
||||||
self.last_subscription = 0
|
def seconds_to_time(total_seconds: float) -> str:
|
||||||
self.last_redemption = 0
|
'''
|
||||||
|
Takes an int or float as an input and it returns a D:HH:MM:SS formatted string.
|
||||||
|
|
||||||
def __str__(self):
|
Parameters:
|
||||||
return f"Earner for {self.connector} with {self.currency} and {self.minimum_amount_in_trading_account} minimum amount in trading account and {self.step_size} step size and {self.percentage} percentage"
|
total_seconds (float): The number of seconds to convert
|
||||||
|
|
||||||
def run(self):
|
Returns:
|
||||||
print(self)
|
str: The formatted string
|
||||||
|
'''
|
||||||
|
|
||||||
|
time_delta = datetime.timedelta(seconds=total_seconds)
|
||||||
|
|
||||||
|
hours = time_delta.seconds//3600
|
||||||
|
remainder = time_delta.seconds%3600
|
||||||
|
minutes = remainder//60
|
||||||
|
seconds = remainder%60
|
||||||
|
|
||||||
|
return f"{time_delta.days}:{hours:02d}:{minutes:02d}:{seconds:02d}"
|
||||||
|
|
||||||
|
|
||||||
if __name__=="__main__":
|
if __name__=="__main__":
|
||||||
|
|
||||||
|
version = "2025.01.06"
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
with open("config.json") as f:
|
with open("config.json") as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
|
||||||
|
|
@ -43,6 +50,8 @@ if __name__=="__main__":
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
threads = []
|
threads = []
|
||||||
|
|
||||||
|
#Run earners
|
||||||
for item in earners:
|
for item in earners:
|
||||||
threads.append(Thread(target=item.run))
|
threads.append(Thread(target=item.run))
|
||||||
for item in threads:
|
for item in threads:
|
||||||
|
|
@ -50,6 +59,42 @@ if __name__=="__main__":
|
||||||
for item in threads:
|
for item in threads:
|
||||||
item.join()
|
item.join()
|
||||||
|
|
||||||
|
#Print status
|
||||||
|
print("="*80)
|
||||||
|
|
||||||
|
subscriptions = []
|
||||||
|
redemptions = []
|
||||||
|
for item in earners:
|
||||||
|
print(item.get_status_string())
|
||||||
|
subscriptions.append(item.get_last_subscription())
|
||||||
|
redemptions.append(item.get_last_redemption())
|
||||||
|
last_subscription = max(subscriptions, key=lambda d: next(iter(d.values())))
|
||||||
|
last_subscription_key = next(iter(last_subscription.keys()))
|
||||||
|
last_subscription_value = next(iter(last_subscription.values()))
|
||||||
|
if last_subscription_value == 0:
|
||||||
|
last_subscription_key = "Never"
|
||||||
|
last_subscription_value = ""
|
||||||
|
else:
|
||||||
|
last_subscription_value = datetime.datetime.fromtimestamp(last_subscription_value).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
last_redemption = max(redemptions, key=lambda d: next(iter(d.values())))
|
||||||
|
last_redemption_key = next(iter(last_redemption.keys()))
|
||||||
|
last_redemption_value = next(iter(last_redemption.values()))
|
||||||
|
if last_redemption_value == 0:
|
||||||
|
last_redemption_key = "Never"
|
||||||
|
last_redemption_value = ""
|
||||||
|
else:
|
||||||
|
last_redemption_value = datetime.datetime.fromtimestamp(last_redemption_value).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
print("-"*80)
|
||||||
|
total_on_trading = sum([item.get_trading_balance() for item in earners])
|
||||||
|
total_on_earning = sum([item.get_earning_balance() for item in earners])
|
||||||
|
print(f"Version {version} | Total funds: {total_on_trading+total_on_earning:.2f} | Total on earn: {total_on_earning:.2f} ({total_on_earning/total_on_trading*100:.2f}%)")
|
||||||
|
print(f"Uptime: {seconds_to_time(time.time()-start_time)} | Last subscription: {last_subscription_key} - {last_subscription_value} | Last redemption: {last_redemption_key} - {last_redemption_value}")
|
||||||
|
|
||||||
|
#Wait for next lap
|
||||||
time.sleep(config["lap_time"])
|
time.sleep(config["lap_time"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
67
notes.txt
67
notes.txt
|
|
@ -1,67 +0,0 @@
|
||||||
'''
|
|
||||||
Subscribe workflow in Binance:
|
|
||||||
1. Get product id
|
|
||||||
2. Subscribe
|
|
||||||
|
|
||||||
Redeem workflow in Binance
|
|
||||||
1. Redeem with the same product id
|
|
||||||
'''
|
|
||||||
#print(binance.get_available_products("USDT"))
|
|
||||||
#print(binance.subscribe_product("USDT001", "10", auto_subscribe=False))
|
|
||||||
#print(binance.get_position("USDT"))
|
|
||||||
#print(binance.redeem_product("USDT001", amount="10"))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
Subscribe workflow in Kucoin
|
|
||||||
1. Get product id
|
|
||||||
2. Subscribe
|
|
||||||
|
|
||||||
Redeem workflow in Kucoin
|
|
||||||
1. Get ORDER id (the order id of the position)
|
|
||||||
2. Redeem
|
|
||||||
'''
|
|
||||||
#print(kucoin.get_available_products("USDT"))
|
|
||||||
#print(kucoin.subscribe_product("2152", "10"))
|
|
||||||
#print(kucoin.get_position("USDT"))
|
|
||||||
#print(kucoin.redeem_product(order_id="2987632", amount="10"))
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
Subscribe workflow in OKX
|
|
||||||
1. Transfer funds to funding account
|
|
||||||
2. Confirm transfer via transfer_id
|
|
||||||
3. Subscribe
|
|
||||||
|
|
||||||
Redeem workflow in OKX
|
|
||||||
1. Reddem product (with coin, no id is required)
|
|
||||||
2. Transfer funds to trading account
|
|
||||||
3. Confirm transfer via transfer_id
|
|
||||||
|
|
||||||
'''
|
|
||||||
#print(okx.get_available_products("USDT"))
|
|
||||||
#print(okx.transfer_to_funding("USDT","10"))
|
|
||||||
#print(okx.get_transfer_state("1064667293"))
|
|
||||||
#print(okx.subscribe_product("USDT", "10"))
|
|
||||||
#print(okx.get_position("USDT"))
|
|
||||||
#print(okx.redeem_product("USDT", "10"))
|
|
||||||
#print(okx.transfer_to_trading("USDT", "10"))
|
|
||||||
#print(okx.get_transfer_state("1064667720"))
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
Subscribe workflow in Gate.io
|
|
||||||
1. Get minimum rate
|
|
||||||
2. Subscribe product
|
|
||||||
3. Use get_account to confirm (request returns error?)
|
|
||||||
|
|
||||||
Redeem workflow in Gate.io
|
|
||||||
1. Reddem product
|
|
||||||
2. Use get_account to confirm (request returns error?)
|
|
||||||
'''
|
|
||||||
|
|
||||||
#print(gateio.get_min_rate("USDT"))
|
|
||||||
#print(gateio.subscribe_product("USDT", "10", "0.00000452"))
|
|
||||||
#print(gateio.get_position("USDT"))
|
|
||||||
#print(gateio.redeem_product("USDT", "10"))
|
|
||||||
Loading…
Reference in New Issue