Esempio n. 1
0
import config, csv
import pandas as pd
from binance.client import Client

client = Client(config.API_KEY, config.API_SECRET)

csvfile = open('symbol_locator.csv', 'w', newline='') 
symbols_writer = csv.writer(csvfile)

symbols = client.futures_position_information()
df = pd.DataFrame(symbols)
df.drop(['positionAmt', 'entryPrice', 'markPrice', 'unRealizedProfit', 'marginType', 'isolatedMargin', 'isAutoAddMargin', 'positionSide', 'liquidationPrice', 'leverage', 'maxNotionalValue'], axis=1, inplace=True)
print(df)

df.to_csv("symbol_locator.csv", index=True, sep=' ')
Esempio n. 2
0
def capital_allocation(symbol, long_or_short):
    # Login info to connect to Binance Bot 1
    key = 'HJw3P8MUWXMHL7q21NaA7Hj0R5A3aA6cAbpzi28cOZcwFP6K21DhHsDToXFDFqb6'
    secret = '6tJDLPX7E34J0Tnfjkc7LRYXGhQaefg8Ib8NXyz3ji2MHNNrFjghr4oyax2o6euz'
    client_bot1 = Client(key, secret)

    position_information = client_bot1.futures_position_information()
    if (long_or_short == 'Long'):
        long_unrealizedPnl = 0
        num_long_positions = 0

        for pos in position_information:
            if (float(pos['positionAmt']) > 0):
                long_unrealizedPnl = long_unrealizedPnl + (float(
                    pos['unRealizedProfit']) / float(pos['notional'])) * 10000
                num_long_positions = num_long_positions + 1

        if (num_long_positions == 0):
            long_unrealizedPnl = 0
        else:
            long_unrealizedPnl = long_unrealizedPnl / num_long_positions

        if (long_unrealizedPnl < -25):
            print('Long Unrealized:', long_unrealizedPnl, '0.00')
            return 0.0
        elif (-25 < long_unrealizedPnl and long_unrealizedPnl <= 50):
            print('Long Unrealized:', long_unrealizedPnl, '0.015')
            return .015
        elif (50 < long_unrealizedPnl and long_unrealizedPnl <= 100):
            print('Long Unrealized:', long_unrealizedPnl, '0.012')
            return .012
        elif (100 < long_unrealizedPnl):
            print('Long Unrealized:', long_unrealizedPnl, '0.01')
            return .01

    if (long_or_short == 'Short'):
        short_unrealizedPnl = 0
        num_short_positions = 0
        for pos in position_information:
            if (float(pos['positionAmt']) < 0):
                short_unrealizedPnl = short_unrealizedPnl + (
                    float(pos['unRealizedProfit']) /
                    (-1 * float(pos['notional']))) * 10000
                num_short_positions = num_short_positions + 1

        if (num_short_positions == 0):
            short_unrealizedPnl = 0
        else:
            short_unrealizedPnl = short_unrealizedPnl / num_short_positions

        if (short_unrealizedPnl < -25):
            print('Short Unrealized:', short_unrealizedPnl, '0.00')
            return 0.0
        elif (-25 < short_unrealizedPnl and short_unrealizedPnl <= 50):
            print('Short Unrealized:', short_unrealizedPnl, '0.015')
            return .015
        elif (50 < short_unrealizedPnl and short_unrealizedPnl <= 100):
            print('Short Unrealized:', short_unrealizedPnl, '0.012')
            return .012
        elif (100 < short_unrealizedPnl):
            print('Short Unrealized:', short_unrealizedPnl, '0.01')
            return .01

    return 0.0
Esempio n. 3
0
class Trader():
    """
    Purpose is to trade live on the Binance Crypto Exchange

    Attributes
    -----------
    symbol: str
    client: Client object - From binance.py
    capital: float - represents how much money is in account
    leverage: float - how many multiples of your money you want to trade
    tf: int - timeframe
    df: pd.DataFrame - data that will be analyzed.
    Methods
    ----------
    load_account
    set_leverage
    set_timeframe
    get_position
    get_necessary_data
    set_asset
    make_row
    load_existing_asset
    start_trading

    Please look at each method for descriptions
    """
    def __init__(self):
        self.start = False
        self.client = None
        self.capital = None
        self.leverage = 1 / 1000
        self.tf = None
        self.symbol = None
        self.loader = _DataLoader()
        self.df = None

    def check_status(self) -> bool:
        """
        Reads a txt file to see whether user wants trading to be on or off
        :return boolean of True or False. True means trading is on, and false means it is off.
        """
        local_path = os.path.dirname(
            os.path.dirname(
                os.path.abspath("__file__"))) + r"\local\trade_status.txt"
        status = pd.read_csv(local_path).set_index('index')
        self.start = bool(status.loc[0, 'status'])

    def load_account(self, additional_balance: int = 20000) -> str:
        """
        Sign in to account using API_KEY and using Binance API
        """
        local_path = os.path.dirname(
            os.path.dirname(
                os.path.abspath("__file__"))) + r"\local\binance_api.txt"
        info = pd.read_csv(local_path).set_index('Name')
        API_KEY = info.loc["API_KEY", "Key"]
        SECRET = info.loc["SECRET", "Key"]
        self.client = Client(API_KEY, SECRET)
        # Initializing how much money I have on the exchange. Sample 20000 has been added.
        self.capital = int(
            float(self.client.futures_account_balance()[0]
                  ['balance'])) + additional_balance
        return "Welcome Haseab"

    def set_leverage(self, leverage: float) -> float:
        """Sets the current leverage of the account: should normally be 1. And 0.001 for testing purposes"""
        self.leverage = leverage
        return self.leverage

    def set_timeframe(self, tf: int) -> int:
        """Sets the timeframe of the trading data"""
        self.tf = tf
        return self.tf

    def get_necessary_data(self, symbol: str, tf: int,
                           max_candles_needed: int) -> pd.DataFrame:
        """
        Gets the minimum necessary data to trade this asset. Only a symbol and timeframe need to be inputted

        Note: This method is used as a way to tackle the 1000 candle limit that is currently on the Binance API.
        A discrete set of ~1000 group candles will be determined, and then the data will be extracted from each,
        using the _get_binance_futures_candles method, and then all of them will be merged together.

        Parameters:
        symbol: str             - Symbol of price ticker   Ex. "BTCUSDT", "ETHUSDT"
        tf: int                 - Timeframe wanted   Ex. 1, 3, 5, 77, 100
        max_candles_needed: int - Maximum candles needed in the desired timeframe     Ex. 231, 770, 1440

        :return pd.DataFrame of candlestick data

        """
        now = time.time()
        df = pd.DataFrame()
        ranges = Helper.determine_candle_positions(max_candles_needed, tf)

        # Grabbing each set of about 1000 candles and appending them one after the other
        for i in range(len(ranges)):
            try:
                df = df.append(
                    self.loader._get_binance_futures_candles(
                        symbol, int(ranges[i]), int(ranges[i + 1]), now))
            except IndexError:
                pass
        return df.drop_duplicates()

    def _update_data(
        self,
        diff: int,
        symbol: str,
    ) -> None:
        """
        Used to update the trading data with the exchange data so that it is real time

        Parameters:
        -----------
        diff: a number that explains how many minutes of disparity there is between current data and live data.

        :return dataframe with the most up-to-date data.
        """
        # Calculating how many minutes to fetch from API
        minutes = math.floor(diff) + 1

        # Getting minute candlestick data. Number of minute candlesticks represented by "minutes" variable
        last_price = self.loader._get_binance_futures_candles(symbol, minutes)
        # Adding a legible Datetime column and using the timestamp data to obtain datetime data
        last_price['Datetime'] = [
            datetime.fromtimestamp(i / 1000) for i in last_price.index
        ]
        last_price = last_price[[
            "Datetime", "Open", "High", "Low", "Close", "Volume"
        ]]

        # Abstracting minute data into appropriate tf
        last_price = self.loader._timeframe_setter(last_price, self.tf, 0)

        # Updating original data with new data.
        self.df = self.df.append(last_price).drop_duplicates()

    def get_position(self, symbol: str) -> float:
        """
        Gets the total amount of current position for a given symbol
        Parameters:
        ------------
        symbol: str
            Ex. "BTCUSDT"
                "ETHUSDT"

        Returns float
            Ex. If a 1.000 BTC position is open, it will return 1.0
        """
        return float([
            i["positionAmt"]
            for i in self.client.futures_position_information()
            if i['symbol'] == symbol
        ][0])

    def set_asset(self, symbol: str, tf: int) -> str:
        """
        Set Symbol of the ticker and load the necessary data with the given timeframe to trade it

        Parameters:
        ------------
        symbol: str     Ex. "BTCUSDT", "ETHUSDT"

        :return str response
        """
        self.symbol = symbol
        max_candles_needed = 231

        # For Binance API purposes, 240 min needs to be inputted as "4h" on binance when fetching data
        map_tf = {
            1: "1m",
            3: "3m",
            5: "5m",
            15: "15m",
            30: "30m",
            60: "1h",
            120: "2h",
            240: "4h",
            360: "6h",
            480: "8h"
        }

        start_time = int((time.time() - self.tf * 235 * 60) * 1000)

        if tf in [1, 3, 5, 15, 30, 60, 120, 240, 360,
                  480]:  # Note: 12H, 1D, 3D, 1W, 1M are also recognized

            # Fetching data from Binance if it matches the eligible timeframe, as it will be faster
            df = Helper.into_dataframe(
                self.client.futures_klines(symbol=symbol,
                                           interval=map_tf[tf],
                                           startTime=start_time))
            df.drop(df.tail(1).index, inplace=True)

        else:
            # If it doesn't match Binance available timeframes, it must be transformed after fetching 1m data.
            df = self.get_necessary_data(symbol, tf, max_candles_needed)
            df = self.loader._timeframe_setter(df, tf)

        # Adding Datetime column for readability of the timestamp. Also more formatting done
        df['Datetime'] = [datetime.fromtimestamp(i / 1000) for i in df.index]
        df = df[["Datetime", "Open", "High", "Low", "Close", "Volume"]]
        df[["Open", "High", "Low", "Close",
            "Volume"]] = df[["Open", "High", "Low", "Close",
                             "Volume"]].astype(float)

        self.df = df

        return f"Symbol changed to {self.symbol}"

    def make_row(
            self,
            high=[],
            low=[],
            volume=[],
            count: int = 0,
            open_price: float = None,
            open_date: str = None
    ) -> (pd.DataFrame, list, list, list, list, list):
        """
        Helper function used to update the last row of a dataframe, using all of the data in the previous "last row" as input.
        This is used to update the price of the candlestick live, with the incomplete current candle constantly updating.

        Parameters:
        -----------
        high:       list        Ex. [23348, 23350, 23335, 23330, 23339]
        low:        list        Ex. [23300, 23345, 23335, 23320, 23300]
        volume:     list        Ex. [47, 31, 110, 117, 2, 55]
        count:      int         Ex. 1,2,3
        open_price: float       Ex. 23342
        open_date:  str         Ex. "2020-08-04 17:33:02"

        Returns tuple -> (pd.DataFrame, list, list, list, list, list)
        """
        # row variable gets a pd.DataFrame of size 1.
        row = self.loader._get_binance_futures_candles("BTCUSDT",
                                                       1).reset_index()
        timestamp = row.loc[0, "Timestamp"]
        close = float(row.loc[0, "Close"])
        high.append(float(row.loc[0, "High"]))
        low.append(float(row.loc[0, "Low"]))
        volume.append(float(row.loc[0, "Volume"]))

        # Initial values of a candle that only get set on the first iteration.
        if count == 0:
            open_price = row.loc[0, "Open"]
            open_date = timestamp

        # Adding to previous candlestick data of the last row by updating the row.
        dfrow = pd.DataFrame([[
            open_date,
            datetime.fromtimestamp(open_date / 1000), open_price,
            max(high),
            min(low), close,
            sum(volume)
        ]],
                             columns=[
                                 "Timestamp", "Datetime", "Open", "High",
                                 "Low", "Close", "Volume"
                             ])

        dfrow[["Open", "High", "Low", "Close",
               "Volume"]] = dfrow[["Open", "High", "Low", "Close",
                                   "Volume"]].astype(float)
        dfrow = dfrow.set_index("Timestamp")

        return dfrow, high, low, volume, open_price, open_date

    def load__existing_asset(self, df: pd.DataFrame) -> pd.DataFrame:
        """Sets the trading data to an already existing dataframe, passed in as an argument"""
        self.df = df
        return self.df

    def start_trading(self,
                      strategy: FabStrategy,
                      executor,
                      tf: int,
                      sensitivity=0,
                      debug=False) -> str:
        """
        Starts the process of trading live. Each minute, the last row of the data is updated and Rule #2 is checked,
        otherwise, it waits till the end of the timeframe where it gets the latest data before it checks the rest of the rules.
        If it does see something following the rules, it will buy/short, given the initial parameters it has. (e.g. leverage, quantity)
        This process continues indefinetly, unless interrupted.

        Returns None.
        """
        count, open_price = 0, 0
        open_date = None
        high, low, volume = [], [], []

        # Loading data into strategy, and creating moving averages.
        strategy.load_data(self.df)
        strategy.create_objects()

        # Checking to see whether trading is on or off. If it is off then it will not enter while loop.
        self.check_status()

        while self.start != False:
            diff = Helper.calculate_minute_disparity(self.df, tf)
            if round(time.time() % 60, 1) == 0 and diff <= tf:

                # Getting the most up-to-date row of the <tf>-min candlestick
                dfrow, high, low, volume, open_price, open_date = self.make_row(
                    high, low, volume, count, open_price, open_date)

                if debug == True:
                    print(dfrow)
                    print(f"{tf - diff} minutes left")

                # Updating moving averages
                strategy.load_data(self.df.append(dfrow))
                strategy.create_objects()

                # Checking only Rule 2, because it needs a minute by minute check.
                # Second condition is making sure that there is no existing position
                if strategy.rule_2_buy_enter(
                        -1, sensitivity) and self.get_position(
                            self.symbol) == 0:
                    trade_info = executor.enter_market(self.symbol, "BUY", 2)
                elif strategy.rule_2_short_enter(
                        -1, sensitivity) and self.get_position(
                            self.symbol) == 0:
                    trade_info = executor.enter_market(self.symbol, "SELL", 2)

                # Saves CPU usage, waits 5 seconds before the next minute
                time.sleep(50)

                count += 1

            elif diff > tf:
                # Updating data using Binance API instead of appending the completed final row from the while loop
                self._update_data(math.floor(diff), "BTCUSDT")

                # Updating Moving averages
                strategy.load_data(self.df)
                strategy.create_objects()

                # Checks for the rest of the rules
                if strategy.rule_2_short_stop(-1) and self.get_position(self.symbol) < 0 and \
                        executor.live_trade_history.last_trade().rule == 2:
                    trade_info = executor.exit_market(
                        self.symbol, 2, self.get_position(self.symbol))
                elif strategy.rule_2_buy_stop(-1) and self.get_position(self.symbol) > 0 and \
                        executor.live_trade_history.last_trade().rule == 2:
                    trade_info = executor.exit_market(
                        self.symbol, 2, self.get_position(self.symbol))
                elif strategy.rule_1_buy_enter(-1) and self.get_position(
                        self.symbol) == 0:
                    trade_info = executor.enter_market(self.symbol, "BUY", 1)
                elif strategy.rule_1_buy_exit(-1) and self.get_position(
                        self.symbol) > 0:
                    trade_info = executor.exit_market(
                        self.symbol, 1, self.get_position(self.symbol))
                elif strategy.rule_1_short_enter(-1) and self.get_position(
                        self.symbol) == 0:
                    trade_info = executor.enter_market(self.symbol, "SELL", 1)
                elif strategy.rule_1_short_exit(-1) and self.get_position(
                        self.symbol) < 0:
                    trade_info = executor.exit_market(
                        self.symbol, 1, self.get_position(self.symbol))
                elif strategy.rule_3_buy_enter(-1) and self.get_position(
                        self.symbol) == 0:
                    trade_info = executor.enter_market(self.symbol, "BUY", 3)
                elif strategy.rule_3_short_enter(-1) and self.get_position(
                        self.symbol) == 0:
                    trade_info = executor.enter_market(self.symbol, "SELL", 3)

                    # Resetting candlesticks
                high, low, volume = [], [], []
                count = 0
                time.sleep(1)

                if debug == True:
                    print(diff)
                    print("next")
            self.check_status()

        return "Trading Stopped"
Esempio n. 4
0
class BinanceWrapperAPI(WrapperAPI):

    # (n) means that parameter is necessary

    def __init__(self, pair, target, precision):
        self.pair = pair
        self.precision = precision
        self.target = target
        self.client = Client(keys.binance_api_key, keys.binance_api_secret)

    def get_my_balance_coin(self, coin):
        balances = self.client.futures_account_balance()
        balance = find(lambda v: v['asset'] == coin, balances)
        return float(balance['withdrawAvailable']) if balance else 0

    def get_mycoin(self):
        return self.get_my_balance_coin('USDT')

    def get_position_targ(self) -> Tuple[float, bool]:
        risks = self.client.futures_position_information(symbol=self.target)
        position = find(lambda v: v['symbol'] == self.pair, risks)
        amt = float(position['positionAmt'])
        return abs(amt), amt >= 0

    def get_balance_interest(self):
        amount, _ = self.get_position_targ()
        return amount

    def buy_order(self, amount: float):
        return self.post_order_market("BUY", amount)

    def sell_order(self, amount: float):
        return self.post_order_market("SELL", amount)

    def post_order_market(self, side: str, quantity: float):
        try:
            res = self.client.futures_create_order(
                symbol=self.pair,
                side=side,
                type="MARKET",
                # positionSide=pside,
                quantity=roundt(quantity, self.precision))
            return [True, res['orderId']]
        except BinanceAPIException as e:
            raise (e)
            return [False, e]

    def get_open_orders(self):
        return self.client.get_open_orders(symbol=self.pair)

    def get_position(self) -> Literal["none", "long", "shor"]:
        amount, posi = self.get_position_targ()
        if amount == 0:
            return 'none'
        return "long" if posi else "shor"

    def get_ask(self):
        return float(self.client.get_ticker(symbol=self.pair)['askPrice'])

    def get_bid(self):
        return float(self.client.get_ticker(symbol=self.pair)['bidPrice'])

    def get_order_status(self, id) -> Literal["COMP", "NEW", "EXPIRE"]:
        try:
            res = self.client.futures_get_order(symbol=self.pair, orderId=id)
            if res['status'] == "FILLED":
                return "COMP"
            # other: CANCELED, PARTIALLY_FILLED
            return "NEW"

        except BinanceAPIException as e:
            return "EXPIRE"
Esempio n. 5
0
class Orders:
    def __init__(self,
                 SYMBOL,
                 LEWAR,
                 PYRAMID_MAX,
                 ORDER_SIZE,
                 is_it_for_real=False):
        self.SYMBOL = SYMBOL
        self.LEWAR = LEWAR
        self.PYRAMID_MAX = PYRAMID_MAX
        self.ORDER_SIZE = ORDER_SIZE

        self.side = {"LONG": 'BUY', "SHORT": 'SELL'}
        self.side_reversed = {
            "SHORT": 'BUY',
            "LONG": 'SELL',
            "BUY": 'SELL',
            "SELL": 'BUY'
        }

        if is_it_for_real:
            with open("api_keys.txt") as d:
                api_keys = d.readlines()
                api_keys[0] = api_keys[0].strip()
            self.client = Client(api_keys[0], api_keys[1])

        self.zagranie_list = []

        try:
            client.futures_change_margin_type(symbol=self.SYMBOL + 'USDT',
                                              marginType="ISOLATED")
        except:
            pass

        self.client.futures_change_leverage(symbol=self.SYMBOL + 'USDT',
                                            leverage=self.LEWAR)

    def update(self):
        l = len(self.zagranie_list)
        for i, zagranie in enumerate(self.zagranie_list[::-1]):
            zagranie.update()
            if zagranie.state == 'closed':
                zagranie.close()
                del zagranie_list[l - 1 - i]

    def order_size(self, price, balance):
        #return 0.6**pyramid*ORDER_SIZE*balance*LEWAR/price
        return self.ORDER_SIZE * balance * self.LEWAR / price

    def get_balance(self):
        a = self.client.futures_account_balance()
        for e in a:
            if e['asset'] == 'USDT':
                return float(e['withdrawAvailable'])

    def positionInfo(self):
        a = self.client.futures_position_information()
        for e in a:
            if e['symbol'] == self.SYMBOL + 'USDT':
                return e

    def create_order(self, side, price=None, TARGET_CHANGE=True):
        print(f"Opening {side}")

        if len(self.zagranie_list) >= self.PYRAMID_MAX:
            print("Pyramid max reached")
            return None

        balance = self.get_balance()

        if price:
            order = self.client.futures_create_order(
                symbol=self.SYMBOL + 'USDT',
                side=self.side[side],
                type='LIMIT',
                timeInForce=TIME_IN_FORCE_GTC,
                quantity=self.order_size(price, balance),
                price=price,
                newOrderRespType="RESULT")
        else:
            order = self.client.futures_create_order(
                symbol=SYMBOL + 'USDT',
                side=self.side[side],
                type='MARKET',
                quantity=self.order_size(
                    self.price, balance),  #JAKIS DOMYSLMY PRICE TRZRBA DAC
                newOrderRespType="RESULT")

        if TARGET_CHANGE:
            if side == "LONG":
                oco_limit_price = self.price * (1 + TARGET_CHANGE)
                oco_stop_price = self.price * (1 - TARGET_CHANGE)
            elif side == "SHORT":
                oco_limit_price = self.price * (1 - TARGET_CHANGE)
                oco_stop_price = self.price * (1 + TARGET_CHANGE)

        zagranie = Zagranie(self, side, order['orderId'], oco_limit_price,
                            oco_stop_price)

        self.zagranie_list.append(zagranie)

        return order['orderId']

    def close(self, side):
        print(f"Closing {side}")

        l = len(self.zagranie_list)
        for i, zagranie in enumerate(self.zagranie_list[::-1]):
            if zagranie.side == side:
                zagranie.close()
                del zagranie_list[l - 1 - i]
Esempio n. 6
0
                                                #callbackRate=1,
                                                ##reduceOnly='True'
                                                )
        order_Sellsl_ID=order_sellsl['orderId']
        print(order_sellsl)
        print("Or der IDsl: " + str(order_Sellsl_ID))    
    """
    buy_price, sell_price, wr_macd_signal = implement_wr_macd_strategy(
        aapl['Close'], aapl['wr_14'], aapl['macd'], aapl['macd_signal'])

    print("la señal vale:", wr_macd_signal)
    # POSITION

    close_price = aapl['Close']

    if client.futures_position_information(
            symbol=symbolo)[-1]['positionAmt'] != "0":
        if client.futures_position_information(
                symbol=symbolo
        )[-1]['positionAmt'] != "0" and wr_macd_signal[
                -1] == -1 and wr_macd_signal[-2] == 0 and COMPRANDO[0] == 1:
            close_price = client.futures_create_order(symbol=symbolo,
                                                      side='SELL',
                                                      type="MARKET",
                                                      quantity=cantidad,
                                                      redueOnly='True')
            telegram_send.send(
                messages=["ORDEN DE CERRADA COMPRA WILL+MAC", symbolo])
            print("ORDEN DE CERRADA COMPRA WILL+MAC", symbolo)
            #if len(client.futures_get_open_orders(symbol=symbolo))!=0:
            #client.futures_cancel_all_open_orders(symbol=symbolo)
        elif client.futures_position_information(
Esempio n. 7
0
while datetime.now() < (launching_time + duration) or  float(dfMarket.loc[dfMarket.index[-1], 'current_position']) != 0.0:
    apiMarkPrice = client.futures_mark_price(symbol =  symbol)
    time = datetime.fromtimestamp(apiMarkPrice['time']/1000).strftime("%Y-%m-%d %H:%M:%S")
    price = apiMarkPrice['markPrice']
    current_values = pd.Series([0]*len(column_names),column_names)

    dfMarket.loc[len(dfMarket)+1] = current_values

    dfMarket.loc[dfMarket.index[-1], 'Time'] = time
    dfMarket.loc[dfMarket.index[-1], 'Mean'] = price
    dfMarket['SMA_3']= dfMarket.iloc[:,1].rolling(window=20).mean()
    dfMarket['SMA_10']= dfMarket.iloc[:,1].rolling(window=100).mean()
    dfMarket['SMA_50']= dfMarket.iloc[:,1].rolling(window=300).mean()

    dfMarket.loc[dfMarket.index[-1], 'total'] = client.futures_account()['totalMarginBalance']
    dfMarket.loc[dfMarket.index[-1], 'current_position'] = client.futures_position_information()[0]['isolatedMargin']
    dfMarket.loc[dfMarket.index[-1], 'Argent Fixe']= client.futures_account()['maxWithdrawAmount']
    dfMarket.loc[dfMarket.index[-1], 'Solde Net'] = client.futures_account()['totalWalletBalance']
    try :
        dfMarket.loc[dfMarket.index[-1], '%PnL'] = (float(client.futures_position_information()[0]['markPrice'])/float(client.futures_position_information()[0]['entryPrice']) -1)* float(client.futures_position_information()[0]['leverage'])*100
    except :
        dfMarket.loc[dfMarket.index[-1], '%PnL'] =  0.0

    #check if the last row of SMA_50 is not empty
    if not (pd.isnull(dfMarket.loc[dfMarket.index[-1], 'SMA_50'])):
        #STRATEGY
        dfMarket.loc[dfMarket.index[-1], 'signals'] = np.where((dfMarket.loc[dfMarket.index[-1], 'SMA_3'] > dfMarket.loc[dfMarket.index[-1], 'SMA_10'] and dfMarket.loc[dfMarket.index[-1], 'SMA_3'] > dfMarket.loc[dfMarket.index[-1], 'SMA_50']),1,0)
        dfMarket.loc[dfMarket.index[-1], 'positions'] = dfMarket.loc[dfMarket.index[-1], 'signals'] - dfMarket.loc[dfMarket.index[-2], 'signals']
        print(float(dfMarket.loc[dfMarket.index[-1], 'current_position']) )
        print(dfMarket.loc[dfMarket.index[-1], 'positions'])
        if dfMarket.loc[dfMarket.index[-1], 'positions'] == 1 and float(dfMarket.loc[dfMarket.index[-1], 'current_position']) == 0.0:
Esempio n. 8
0
import binance
from binance.client import Client
from auth import key, secret
import math
import time
from datetime import datetime, timedelta
import requests
import json
from notify_run import Notify
import tuning

# Initiate notify and binance clients
notify = Notify()
client = Client(key, secret)

position = client.futures_position_information()[0]
if abs(float(position["positionAmt"])) < 0.001:
    holding = 0
    holdingBTC = 0
    lastbuy = 0
    lastsell = 0
elif float(position['liquidationPrice']) < float(position['entryPrice']):
    holding = 1
    holdingBTC = float(position['positionAmt'])
    lastbuy = float(position['entryPrice'])
    lastsell = 0
else:
    holding = -1
    holdingBTC = float(position['positionAmt']) * -1
    lastbuy = 0
    lastsell = float(position['entryPrice'])
Esempio n. 9
0
File: trader.py Progetto: haseab/FAB
class Trader():
    """
    Purpose is to trade live on the Binance Crypto Exchange

    Attributes
    -----------
    symbol: str
    client: Client object - From binance.py
    capital: float - represents how much money is in account
    leverage: float - how many multiples of your money you want to trade
    tf: int - timeframe
    df: pd.DataFrame - data that will be analyzed.
    Methods
    ----------
    load_account
    set_leverage
    set_timeframe
    get_position
    get_necessary_data
    set_asset
    make_row
    load_existing_asset
    start_trading

    Please look at each method for descriptions
    """
    def __init__(self, binance=True, qtrade=False, db=False, ib=False):
        if binance:
            self.binance = Client()
        # self.ftx = FtxClient()
        self.capital = None
        self.leverage = 1
        self.tf = None
        self.executor = TradeExecutor()
        self.loader = _DataLoader(db=db, qtrade=qtrade, ib=ib)
        self.illustrator = Illustrator()
        self.strategy = FabStrategy()
        self.order_history = pd.DataFrame()
        self.trade_replay = []
        self.precisions = {
            symbol_dic['symbol']: symbol_dic['quantityPrecision']
            for symbol_dic in self.loader.binance.futures_exchange_info()
            ['symbols']
        }

    def load_account(self, additional_balance: int = 0) -> str:
        """
        Sign in to account using API_KEY and using Binance API
        """
        # local_path_binance = os.path.dirname(os.path.dirname(os.path.abspath("__file__"))) + r"\local\binance_api.txt"
        # local_path_ftx = os.path.dirname(os.path.dirname(os.path.abspath("__file__"))) + r"\local\ftx_api.txt"
        # info_binance = pd.read_csv(local_path_binance).set_index('Name')
        # info_ftx = pd.read_csv(local_path_ftx).set_index('Name')

        API_KEY_BINANCE = config('API_KEY_BINANCE')
        API_SECRET_BINANCE = config('API_SECRET_BINANCE')

        # API_KEY_FTX = config('API_KEY_FTX')
        # API_SECRET_FTX  = config('API_SECRET_FTX')

        self.binance = Client(api_key=API_KEY_BINANCE,
                              api_secret=API_SECRET_BINANCE)
        # self.ftx = FtxClient(api_key=API_KEY_FTX, api_secret=API_SECRET_FTX)
        return "Connected to Binance"

    def get_capital(self, additional_balance=4944.2649865):
        initial_margin = float(
            self.binance.futures_account()['totalInitialMargin'])
        available_balance = float(
            self.binance.futures_account()['availableBalance'])
        self.capital = (initial_margin + available_balance +
                        additional_balance) * self.leverage
        return self.capital

    def load_futures_trading_history(self, start_time, end_time=None):
        df = pd.DataFrame()
        ranges = Helper.determine_timestamp_positions(start_time,
                                                      end_time,
                                                      limit=1)

        for index, timestamp in enumerate(ranges):
            try:
                df = df.append(
                    pd.DataFrame(
                        self.binance.futures_account_trades(
                            startTime=ranges[index],
                            endTime=ranges[index + 1])))
            except (IndexError) as e:
                pass
        return df.reset_index(drop=True)

    def get_tickers(self):
        tickers = pd.DataFrame(self.binance.futures_ticker())
        tickers = tickers.rename(
            {
                'lastPrice': 'close',
                'openPrice': 'open',
                'highPrice': 'high',
                'lowPrice': 'low',
                'openTime': 'timestamp'
            },
            axis=1)
        tickers['date'] = Helper.millisecond_timestamp_to_datetime(
            tickers['timestamp'])
        return tickers[[
            'symbol', 'timestamp', 'date', 'open', 'high', 'low', 'close',
            'volume'
        ]].set_index('symbol')

    def show_live_chart(self, symbol, tf, refresh_rate=1):
        df_tf_sma = self.show_current_chart(symbol, tf)
        while True:
            Helper.sleep(refresh_rate)
            clear_output(wait=True)
            df_tf_sma = self.show_current_chart(symbol, tf, data=df_tf_sma)

    def show_current_chart(self, symbol=None, tf=None, data=()):
        if len(data) == 0:
            data = self.set_asset(symbol,
                                  tf,
                                  max_candles_needed=375,
                                  futures=True)
        else:
            row = self.set_asset(symbol,
                                 tf,
                                 max_candles_needed=1,
                                 futures=True)
            if data['date'].iloc[-1] == row['date'].iloc[-1]:
                data = data[:-1].append(row)
            else:
                data = data.append(row)

        tf_data = data['tf'].iloc[0]
        df_tf = self.loader._timeframe_setter(
            data, tf // tf_data, keep_last_row=True) if tf != tf_data else data
        return self.illustrator.graph_df(df_tf, sma=False)

    def get_necessary_data(self,
                           symbol: str,
                           tf: int,
                           max_candles_needed: int = 235) -> pd.DataFrame:
        df = pd.DataFrame()
        start_datetime = str(
            Helper.datetime_from_tf(tf,
                                    daily_1m_candles=1440,
                                    max_candles_needed=max_candles_needed)[0])
        df = df.append(
            self.loader.get_binance_candles(symbol,
                                            tf,
                                            start_date=start_datetime))
        df['symbol'] = [symbol for _ in range(len(df))]
        return df.drop_duplicates()

    def get_necessary_data_futures(
            self,
            symbol: str,
            tf: int,
            max_candles_needed: int = 245) -> pd.DataFrame:
        """
        Gets the minimum necessary data to trade this asset.

        Note: This method is used as a way to tackle the 1000 candle limit that is currently on the Binance API.
        A discrete set of ~1000 group candles will be determined, and then the data will be extracted from each,
        using the _get_binance_futures_candles method, and then all of them will be merged together.

        Parameters:
        symbol: str             - Symbol of price ticker   Ex. "BTCUSDT", "ETHUSDT"
        tf: int                 - Timeframe wanted   Ex. 1, 3, 5, 77, 100
        max_candles_needed: int - Maximum candles needed in the desired timeframe     Ex. 231, 770, 1440

        :return pd.DataFrame of candlestick data

        """
        now = time.time()
        df = pd.DataFrame()
        ranges = Helper.determine_candle_positions(max_candles_needed, tf)
        for i in range(len(ranges)):
            try:
                df = df.append(
                    self.loader._get_binance_futures_candles(
                        symbol, tf, int(ranges[i]), int(ranges[i + 1]), now))
            except IndexError:
                pass
        df['symbol'] = [symbol for _ in range(len(df))]
        return df.drop_duplicates()

    def get_single_asset_signals(self,
                                 screener,
                                 symbol,
                                 tf,
                                 enter=True,
                                 shift=0):
        df = self.set_asset(symbol, tf, max_candles_needed=245)
        binance_df = int(df['tf'].iloc[0])
        df_tf = self.loader._timeframe_setter(df,
                                              tf // binance_df,
                                              keep_last_row=True,
                                              shift=shift)
        strat = FabStrategy()
        df_ma = strat.load_data(df_tf)
        return df_ma, screener._check_for_tf_signals(df_ma,
                                                     max_candle_history=10,
                                                     enter=enter)

    def set_asset(self,
                  symbol: str,
                  tf: int,
                  max_candles_needed: int = 245,
                  futures=False) -> pd.DataFrame:
        binance_tf = Helper.find_greatest_divisible_timeframe(tf)
        new_max_candles = max_candles_needed * (tf // binance_tf)
        if futures:
            df = self.get_necessary_data_futures(symbol, binance_tf,
                                                 new_max_candles)
            return df
        df = self.get_necessary_data(symbol, binance_tf, new_max_candles)
        self.df, self.tf, self.symbol = df, tf, symbol
        return df

    def get_current_trade_progress(self, key=()) -> pd.DataFrame:
        if len(key) == 0:
            key = self.key

        df = pd.DataFrame(self.binance.futures_position_information())
        df[['positionAmt', 'entryPrice',
            'markPrice']] = df[['positionAmt', 'entryPrice',
                                'markPrice']].astype(float)
        df = df[df['positionAmt'] != 0][[
            'symbol', 'positionAmt', 'entryPrice', 'markPrice'
        ]].reset_index(drop=True)
        df = df.rename(
            {
                'positionAmt': 'size',
                'entryPrice': 'enter price',
                'markPrice': 'current price'
            },
            axis=1)
        df['side'] = np.where(df['size'] > 0, 'BUY', 'SELL')
        df['size'] = df['size'].abs()
        df['usd size'] = df['size'] * df['enter price']

        short_profitability = (
            (0.9996**2) *
            (2 - df['current price'] / df['enter price']) - 1) * 100
        long_profitability = (
            (0.9996**2) * (df['current price'] / df['enter price']) - 1) * 100

        df['pnl (%)'] = np.where(df['side'] == 'SELL', short_profitability,
                                 long_profitability)
        df['pnl (USD)'] = df['usd size'] * (df['pnl (%)'] / 100)
        df['share'] = df['usd size'] / df['usd size'].sum()
        df = df.round(2)
        df = df[[
            'symbol', 'side', 'enter price', 'size', 'usd size',
            'current price', 'pnl (%)', 'pnl (USD)', 'share'
        ]]

        current_positions = df

        if type(key) != type(None):
            recent_signals = pd.read_csv(
                r"C:\Users\haseab\Desktop\Python\PycharmProjects\FAB\local\Workers\Recent signals.txt"
            )
            current_positions['tf'] = [
                int(recent_signals.set_index('symbol').loc[symbol, 'tf'])
                for symbol in current_positions['symbol'].values
            ]
            current_positions = self.key[['win loss rate',
                                          'avg pnl']].reset_index().merge(
                                              current_positions,
                                              on=['symbol', 'tf'])

        self.current_positions = current_positions
        return current_positions

    def _check_trade_close(self, screener, current_positions):
        trades_to_close = []

        for symbol, tf in current_positions.reset_index().set_index(
            ['symbol', 'tf']).index:
            try:
                df_tf = screener.df_dic[(symbol, tf)]
                df_ma = self.strategy.load_data(df_tf)
                display(Markdown(f"## {symbol} {tf}"))
                display(self.illustrator.graph_df(df_ma[-50:], flat=True))
                enter_signal, enter_x_last_row, *rest = screener._check_for_tf_signals(
                    df_tf, max_candle_history=10, enter=True)
                close_signal, exit_x_last_row, *rest = screener._check_for_tf_signals(
                    df_tf, max_candle_history=10, enter=False)

                self.df_tf, self.close_signal, self.exit_x_last_row = df_tf, close_signal, exit_x_last_row,

                if close_signal:
                    # raise Exception(close_signal, exit_x_last_row, enter_x_last_row)
                    if enter_x_last_row and exit_x_last_row < enter_x_last_row:
                        continue

                    last_entry_date = pd.Timestamp(
                        self.recent_signals.reset_index().set_index(
                            ['symbol', 'tf']).loc[(symbol, tf), 'date'])
                    last_exit_date = self.df['date'].iloc[self.exit_x_last_row]
                    if last_entry_date > last_exit_date:
                        print('failed')
                        continue

                    trades_to_close.append(symbol)
                    print(f'{symbol} Trade Closed')
            except AttributeError as e:
                return []

        return trades_to_close

    def trade_free_capital(self, executor, current_positions,
                           remaining_to_invest, trades_to_enter):
        print("-----------------------------------------------")
        print(f"Free capital: {remaining_to_invest} USD")
        print("-----------------------------------------------", end="\n\n\n")
        final_trades_to_enter = self.check_against_max_trade_size(
            trades_to_enter, current_positions, self.max_trade_size)
        self.order_history = self.order_history.append(
            executor.enter_market(client=self.binance,
                                  symbol_side_rule=final_trades_to_enter,
                                  remaining_capital=remaining_to_invest,
                                  number_of_trades=len(trades_to_enter),
                                  reason='free_capital',
                                  max_trade_size=self.max_trade_size))
        display(self.order_history.tail(len(trades_to_enter)))
        self.order_history.to_csv("FAB Order History.csv")
        self.trade_replay.append(
            self.get_current_trade_progress(printout=False))

    def calculate_remaining_capital(self, current_positions, capital):
        total_invested = current_positions['usd size'].sum(
        ) if len(current_positions) > 0 else 0
        remaining_to_invest = capital - total_invested
        return remaining_to_invest

    def get_positions_amount(self,
                             list_of_symbols: list,
                             full_close=False,
                             divide_by=1,
                             max_trades=3) -> list:
        """
        Gets the total amount of current position for a given symbol
        Parameters:
        ------------
        symbol: str
            Ex. "BTCUSDT"
                "ETHUSDT"

        Returns float
            Ex. If a 1.000 BTC position is open, it will return 1.0
        """
        # [{'symbol':'CHRUSDT', 'positionAmt':1}]
        position_values = {}
        for symbol in list_of_symbols:
            last_price = float(
                self.binance.futures_mark_price(symbol=symbol)['markPrice'])

            for coin_futures_info in self.binance.futures_position_information(
            ):
                if coin_futures_info['symbol'] == symbol:
                    amount = float(coin_futures_info["positionAmt"])
                    amount = round(amount, self.precisions[symbol])
                    if divide_by > 1:
                        amount = round(amount - amount / divide_by,
                                       self.precisions[symbol])
                        position_values[
                            symbol] = amount if amount > 0 else 10**(
                                -self.precisions[symbol])
                    if full_close:
                        position_values[symbol] = amount
                    else:
                        return position_values
        return position_values

    def get_key(self,
                essential_metrics,
                win_loss_threshold=0.350,
                pnl_threshold=1.025,
                data_point_threshold=5):
        key = essential_metrics[
            essential_metrics['amount of data'] >= data_point_threshold]
        key = key[key['avg pnl'] > pnl_threshold]
        key = key[key['win loss rate'] > win_loss_threshold]
        key['win loss rate'] = key['win loss rate'].round(1)
        key['wnl drawdown'] = 0.4 * key['win loss rate'] + 0.6 * key[
            'longest drawdown']
        master_key = key.reset_index().set_index(['symbol', 'tf']).sort_values(
            'wnl drawdown', ascending=False)
        # master_key = key.reset_index().set_index(['symbol', 'tf']).sort_values(by=['win loss rate', 'avg pnl'], ascending=[False, False])
        self.key = master_key
        return master_key

    def _profit_optimization(self, key, current_positions, trades_to_enter,
                             number_of_trades):
        """
        Returns:
            final_trades_to_enter: Ex. [('ZILUSDT', "Short", 'Rule 2'), ('BTCUSDT', 'Long', 'Rule 1'), ("ETHUSDT", "Short", 'Rule 3')]
            trades_to_close:       Ex. ['ADAUSDT']
        """
        print()
        print("Optimizing Trades:... ")

        temp_metrics = key.reset_index().set_index(
            ['symbol', 'side', 'rule no'])
        trades_of_interest = [(symbol,
                               int(temp_metrics.loc[(symbol, side, rule),
                                                    'tf']))
                              for symbol, side, rule in trades_to_enter
                              if (symbol, side, rule) in temp_metrics.index]

        if not trades_of_interest:
            print("Didn't make it past key filter", end='\n\n')
            return [], []

        current_position_symbols_tf_pair = Helper().nparray_to_tuple(
            current_positions.reset_index()[['symbol', 'tf']].values)

        all_symbols = list(
            set(trades_of_interest).union(
                set(current_position_symbols_tf_pair)))

        self.current_position_symbols_tf_pair, self.trades_of_interest, self.all_symbols = current_position_symbols_tf_pair, trades_of_interest, all_symbols

        self.top_x_symbols = sorted(
            all_symbols,
            key=lambda x: (key.loc[x, 'win loss rate'], key.loc[x, 'avg pnl']),
            reverse=True)[:number_of_trades]

        partial_trades_to_enter = list(
            set(self.top_x_symbols).intersection(
                set(trades_of_interest)).difference(
                    set(current_position_symbols_tf_pair)))
        trades_to_close = list(
            set(current_position_symbols_tf_pair).difference(
                set(self.top_x_symbols)))
        trades_to_close = [symbol for symbol, tf in trades_to_close]

        final_trades_to_enter = [
            (symbol, side, rule)
            for (symbol,
                 tf), (symbol, side,
                       rule) in zip(trades_of_interest, trades_to_enter)
            if (symbol, tf) in partial_trades_to_enter
        ]

        for tup in trades_of_interest:
            if tup in final_trades_to_enter:
                raise Exception(tup, trades_of_interest, final_trades_to_enter)

        return trades_to_close, final_trades_to_enter

    def get_dividing_factor(self, current_positions, final_trades_to_enter,
                            number_of_trades):
        dividing_factor = (len(current_positions) +
                           len(final_trades_to_enter)) / len(current_positions)
        minimum_threshold = current_positions['usd size'].sum() * 0.95 // len(
            current_positions)
        if dividing_factor > 1 and minimum_threshold > (
                self.capital) // number_of_trades:
            print(minimum_threshold, (self.capital) // number_of_trades)
            return dividing_factor
        return 1

    def optimize_trades(self, executor, current_positions, trades_to_enter,
                        number_of_trades):
        if len(current_positions) != 0:
            self.position_capital = self.get_capital()
            trades_to_close, final_trades_to_enter = self._profit_optimization(
                self.key, current_positions, trades_to_enter, number_of_trades)

            if trades_to_close:
                self.order_history = self.order_history.append(
                    executor.exit_market(self.binance,
                                         self.get_positions_amount(
                                             trades_to_close, full_close=True),
                                         reason='lower rank'))
                display(self.order_history)
                current_positions = self.get_current_trade_progress(
                    printout=False)

            if final_trades_to_enter:
                dividing_factor = self.get_dividing_factor(
                    current_positions, final_trades_to_enter, number_of_trades)
                positions_amount = self.get_positions_amount(
                    current_positions['symbol'].values,
                    divide_by=dividing_factor,
                    max_trades=number_of_trades)

                if positions_amount:
                    self.order_history = self.order_history.append(
                        executor.exit_market(self.binance,
                                             positions_amount,
                                             reason='making space'))
                self.position_capital = self.get_capital()
                final_trades_to_enter = self.check_against_max_trade_size(
                    final_trades_to_enter, current_positions,
                    self.max_trade_size)
                self.remaining_capital = self.calculate_remaining_capital(
                    current_positions, self.position_capital)
                self.order_history = self.order_history.append(
                    executor.enter_market(self.binance,
                                          final_trades_to_enter,
                                          self.remaining_capital,
                                          len(final_trades_to_enter),
                                          reason='higher rank',
                                          max_trade_size=self.max_trade_size))
                display(self.order_history)
            else:
                print("No Trades made")

        self.trades_to_close, self.final_trades_to_enter = trades_to_close, final_trades_to_enter
        self.order_history.to_csv("FAB Order History.csv")
        self.trade_replay.append(
            self.get_current_trade_progress(printout=False))

    def close_any_old_trades(self, screener, executor, current_positions):
        if len(current_positions) == 0:
            return False
        trades_to_close = self._check_trade_close(screener, current_positions)
        if trades_to_close:
            self.order_history = self.order_history.append(
                executor.exit_market(self.binance,
                                     self.get_positions_amount(
                                         trades_to_close, full_close=True),
                                     reason='trade closed'))

    def update_trades_to_enter(self, current_positions, trades_to_enter):
        if len(trades_to_enter) == 0:
            trades_to_enter = [(symbol, self.executor.dic[side], None)
                               for symbol, side in current_positions[
                                   ['symbol', 'side']].values]
        return trades_to_enter

    def check_against_max_trade_size(self, trades_to_enter, current_positions,
                                     max_trade_size):
        final_trades_to_enter = []
        for symbol, side, rule in trades_to_enter:
            if symbol in current_positions[
                    'symbol'].values and current_positions.set_index(
                        'symbol').loc[symbol,
                                      'usd size'] >= max_trade_size * 0.99:
                print('worked')
                continue
            final_trades_to_enter.append((symbol, side, rule))
        return final_trades_to_enter

    def monitor_fab(self,
                    screener,
                    df_metrics,
                    tfs,
                    number_of_trades=3,
                    leverage=1,
                    recency=-1,
                    additional_balance=0,
                    max_trade_size=None):
        # self.order_history = pd.DataFrame()
        self.load_account()
        executor = self.executor
        self.leverage = leverage

        essential_metrics = Helper.drop_extra_delays(df_metrics,
                                                     screener.tf_delay_match)
        self.starting_capital = self.get_capital(
            additional_balance=additional_balance)
        self.max_trade_size = max_trade_size
        self.key = self.get_key(essential_metrics)
        # self.key.to_csv ('Optimization Function Key.csv')

        now = Helper.current_minute_datetime()
        while True:
            if datetime.now() >= now + pd.Timedelta(1, 'minute'):
                clear_output(wait=True)
                print("Current time: \t", datetime.now(), end='\n\n')

                current_positions = self.get_current_trade_progress(
                    key=self.key)
                if len(current_positions) > number_of_trades:
                    raise Exception(
                        f"You have more than {number_of_trades} active trades! Close first"
                    )
                if current_positions['usd size'].sum(
                ) > self.starting_capital * 1.5:
                    raise Exception('We are too overexposed!',
                                    current_positions['usd size'].sum())

                self.close_any_old_trades(screener, executor,
                                          current_positions)

                remaining_capital = self.calculate_remaining_capital(
                    current_positions, self.capital)

                ## trades_to_enter is a list of lists (Ex. [('BANDUSDT', 'Short', 'Rule2'), ('BCHUSDT', 'Short', 'Rule 1')]
                ## df_recent_signals is a regular screener dataframe

                trades_to_enter, recent_signals = screener.top_trades(
                    trader=self,
                    df_metrics=df_metrics,
                    tfs=tfs,
                    n=number_of_trades,
                    recency=recency)

                self.trades_to_enter, self.recent_signals = trades_to_enter, recent_signals

                print("Signals:")
                display(recent_signals)

                trades_left = number_of_trades - len(current_positions)

                if remaining_capital > 100 and trades_left > 0 and trades_to_enter:
                    self.trade_free_capital(executor, current_positions,
                                            remaining_capital, trades_to_enter)

                elif remaining_capital > 100 and len(current_positions) != 0:
                    trades_to_enter = self.update_trades_to_enter(
                        current_positions=current_positions,
                        trades_to_enter=trades_to_enter)
                    self.trade_free_capital(executor, current_positions,
                                            remaining_capital, trades_to_enter)
                elif not trades_to_enter:
                    Helper.sleep(60)
                    now = Helper.current_minute_datetime()
                    continue
                else:
                    print("Leverage: ", self.leverage)
                    print("Trades to Enter: ", trades_to_enter)
                    print("Max Trades: ", number_of_trades)
                    self.optimize_trades(executor, current_positions,
                                         trades_to_enter, number_of_trades)
                Helper.sleep(60)
                now = Helper.current_minute_datetime()
                print()
            Helper.output_loading()