import time import datetime from libraries.balance_accounts import balance_accounts from libraries.colors import colors from decimal import Decimal, getcontext, ROUND_DOWN 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.is_paused = False self.status_string = "" getcontext().prec = 8 getcontext().rounding = ROUND_DOWN def __str__(self): return str(self.connector) def write_to_log(self,message): with open("earn.log", "a") as f: f.write(str(self.connector) + datetime.datetime.now().strftime(' [%Y/%m/%d %H:%M:%S] ') + message + "\n") def toggle_pause(self): self.is_paused = not self.is_paused return self.is_paused def get_is_paused(self): return self.is_paused def set_step_size(self, step_size): try: self.step_size = float(step_size) return self.step_size except Exception as e: print(e) self.write_to_log(str(e)) return 0 def get_step_size(self): return self.step_size def set_percentage(self, percentage): try: self.percentage = float(percentage) return self.percentage except Exception as e: print(e) self.write_to_log(str(e)) return 0 def get_percentage(self): return self.percentage def set_minimum_amount_in_trading_account(self, minimum_amount_in_trading_account): try: self.minimum_amount_in_trading_account = float(minimum_amount_in_trading_account) return self.minimum_amount_in_trading_account except Exception as e: print(e) self.write_to_log(str(e)) return 0 def get_minimum_amount_in_trading_account(self): return self.minimum_amount_in_trading_account def set_time_between_subscriptions(self, time_between_subscriptions): try: self.time_between_subscriptions = float(time_between_subscriptions) return self.time_between_subscriptions except Exception as e: print(e) self.write_to_log(str(e)) return 0 def get_time_between_subscriptions(self): return self.time_between_subscriptions def set_time_between_redemptions(self, time_between_redemptions): try: self.time_between_redemptions = float(time_between_redemptions) return self.time_between_redemptions except Exception as e: print(e) self.write_to_log(str(e)) return 0 def get_time_between_redemptions(self): return self.time_between_redemptions 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"{datetime.datetime.now().strftime('[%Y/%m/%d %H:%M:%S]')} | {str(self.connector).upper()} | Subscribing {amount} {self.currency}") self.write_to_log(f"Subscribing {amount} {self.currency}") available_product = self.connector.get_available_products(self.currency) subscription = {} if available_product["coin"]==self.currency: #Every exchange has it own subscription method if str(self.connector) in ["binance","kucoin"]: subscription = self.connector.subscribe_product(available_product["product_id"],amount) elif str(self.connector)=="gateio": min_rate = self.connector.get_min_rate(available_product["coin"])["min_rate"] time.sleep(.5) #For the sake of the API subscription = self.connector.subscribe_product(available_product["product_id"],amount,min_rate) elif str(self.connector)=="okx": transfer = self.connector.transfer_to_funding(available_product["coin"],str(amount)) if "Success" in transfer: transfer_state = self.connector.get_transfer_state(transfer["transId"]) if "Success" in transfer_state: subscription = self.connector.subscribe_product(available_product["product_id"],amount) else: print(f"{str(self.connector)} - Transfer of funds state query failed!") self.write_to_log("Transfer of funds state query failed! - " + str(subscription)) return 1 else: print(f"{str(self.connector)} - Transfer of funds failed!") self.write_to_log("Transfer of funds failed! - " + str(transfer)) return 1 if "Success" in subscription: self.last_subscription_time = time.time() return 0 self.write_to_log("Subscription failed! - " + str(subscription)) return 1 def redeem(self,amount): #Redeem print(f"{datetime.datetime.now().strftime('[%Y/%m/%d %H:%M:%S]')} | {str(self.connector).upper()} | Redeeming {amount} {self.currency}") self.write_to_log(f"Redeeming {amount} {self.currency}") available_product = self.connector.get_available_products(self.currency) redemption = {} if available_product["coin"]==self.currency: if str(self.connector) in ["binance","gateio"]: redemption = self.connector.redeem_product(available_product["product_id"],amount=amount) elif str(self.connector)=="kucoin": position = self.connector.get_position(self.currency) if "Error" not in position: redemption = self.connector.redeem_product(position["positionId"],amount=amount) time.sleep(1) #The funds go to the funding account - transfer them to the trading account. transfer_step = self.connector.transfer_to_trading(self.currency, amount) else: print(f"{str(self.connector)} - Position not found!") self.write_to_log("Position not found! " + str(position)) return 1 elif str(self.connector)=="okx": redemption_step = self.connector.redeem_product(self.currency, amount=amount) if "Success" in redemption_step: time.sleep(1) #Breathing room funding_balance = self.connector.get_funding_balance(self.currency) transfer_step = self.connector.transfer_to_trading(self.currency, funding_balance[self.currency]) if "Success" in transfer_step: redemption = self.connector.get_transfer_state(transfer_step["transId"]) else: print(f"{str(self.connector)} - Transfer step failed!") self.write_to_log("Transfer step failed! " + str(transfer_step)) return 1 else: print(f"{str(self.connector)} - Redemption step failed!") self.write_to_log("Redemption step failed! " + str(redemption_step)) return 1 if "Success" in redemption: self.last_redemption_time = time.time() return 0 self.write_to_log("Redemption failed! - " + str(redemption)) 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 paused_string = "" if not self.is_paused: target_trading_amount, target_earning_amount = balance_accounts(Decimal(self.trading_balance), Decimal(self.earning_balance), Decimal(self.minimum_amount_in_trading_account), Decimal(self.step_size), Decimal(self.percentage)) earning_delta = Decimal(0) if self.earning_balance is None: print(f"{str(self.connector).upper()} - There was an error fetching earning balance") else: if float(self.earning_balance)!=0: earning_delta = target_earning_amount - Decimal(self.earning_balance) if earning_delta>Decimal(self.step_size) and time.time()-self.last_subscription_time>self.time_between_subscriptions: self.subscribe(earning_delta) if earning_delta<-Decimal(self.step_size) and time.time()-self.last_redemption_time>self.time_between_redemptions: self.redeem(-earning_delta) #print(f"{str(self.connector)} - Difference: {earning_delta}") else: paused_string = "| "+colors.yellow+"PAUSED"+colors.white #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}" total_balance = float(self.earning_balance)+float(self.trading_balance) percentages_string = f"On earn: {float(self.earning_balance)/total_balance:.2%} {paused_string}" self.status_string = f"{colors.cyan}{str(self).upper()}{colors.white} | {balances_string} | {percentages_string}"