more work

This commit is contained in:
Nicolás Sánchez 2025-01-06 23:26:29 -03:00
parent ef99063dae
commit 5e7ab5a09d
6 changed files with 187 additions and 86 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ libraries/wrappers/__pycache__/*
*.pyc
*.pyo
credentials.py
some_tests.py

View File

@ -1,5 +1,9 @@
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:
if spot_balance < target_spot_balance:

117
libraries/earner.py Normal file
View File

@ -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}"

View File

@ -27,6 +27,7 @@ class binance_earn:
for item in account["balances"]:
if item["asset"]==coin:
return {coin: item["free"]}
return {"Error": "Coin not found"}
def get_available_products(self, coin):

81
main.py
View File

@ -3,32 +3,39 @@ from libraries.wrappers import earn_binance
from libraries.wrappers import earn_kucoin
from libraries.wrappers import earn_okx
from libraries.wrappers import earn_gateio
from libraries.earner import earner
from threading import Thread
import time
import datetime
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
self.last_redemption = 0
def __str__(self):
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"
def run(self):
print(self)
def seconds_to_time(total_seconds: float) -> str:
'''
Takes an int or float as an input and it returns a D:HH:MM:SS formatted string.
Parameters:
total_seconds (float): The number of seconds to convert
Returns:
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__":
version = "2025.01.06"
start_time = time.time()
with open("config.json") as f:
config = json.load(f)
@ -43,13 +50,51 @@ if __name__=="__main__":
while True:
threads = []
#Run earners
for item in earners:
threads.append(Thread(target=item.run))
for item in threads:
item.start()
for item in threads:
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"])

View File

@ -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"))