def __init__(self, mode):

        # Set bot mode
        self.mode = mode

        # In case something goes wrong
        self.error = False

        # Period over which calculations will be made
        self.PERIOD = 20

        # Display header
        display_header()

        # Enter asset
        self.symbol = enter_data()

        if self.mode == 'active':
            # Setup Plot
            plt.style.use('seaborn')
            self.fig, self.ax = plt.subplots()

            # Account references
            self.__orders = Orders()
            self.__account = Account()
            self.__market = Market()

            # Dataframe to store data
            self.df = pd.DataFrame()

            # Qty to purchase
            self.QTY = 1000

            # Track buy price
            self.buy_price = 0

            # Tracks position status
            self.in_position = False

            # Tracks the close prices
            self.closes = []

            # Init websocket
            self.ws = WebSocket(self)

            # Setup the plot's process
            self.p = Process(target=self.plot_live_graph)

        elif self.mode == 'test':
            # self.position = False
            self.hist_df = pd.DataFrame()
Beispiel #2
0
    def __init__(self, mode):

        # In case of any errors
        self.error = False

        # Display Header
        display_header()

        # Bot mode
        self.mode = mode

        # Constants
        self.PERIOD = 14
        self.HIGH = 80
        self.LOW = 20
        self.MFI_MARGIN = 3

        # Assign variables
        self.symbol = enter_data()

        if self.mode == 'active':
            # Setup Plot
            plt.style.use('seaborn')
            self.fig, (self.ax1, self.ax2) = plt.subplots(2, 1)

            # Account references
            self.__orders = Orders()
            self.__account = Account()
            self.__market = Market()

            # Dataframe to store data
            self.df = pd.DataFrame()

            # Qty to purchase
            self.QTY = 1000

            # Tracks position status
            self.in_position = False

            # Keeps track of the buying price
            self.buy_price = 0

            # Init websocket
            self.ws = WebSocket(self)

            # Setup the plot's process
            self.p = Process(target=self.plot_live_graph)

        elif self.mode == 'test':
            self.hist_df = pd.DataFrame()
            self.mfi = None
Beispiel #3
0
    def __init__(self, mode):

        # In case of any error
        self.error = False

        # Bot mode
        self.mode = mode

        # Display Header
        display_header()

        self.symbol = enter_data()

        if self.mode == 'active':
            # Setup Plot
            plt.style.use('seaborn')
            self.fig, self.ax = plt.subplots()

            # Account references
            self.__orders = Orders()
            self.__account = Account()
            self.__market = Market()

            # Dataframe to store data
            self.df = pd.DataFrame()

            # Qty to purchase
            self.QTY = 50

            # Tracks position status
            self.in_position = False

            # Tracks the close prices
            self.closes = []

            # Init websocket
            self.ws = WebSocket(self)

            # Track buy price
            self.buy_price = 0

            # Setup the plot's process
            self.p = Process(target=self.plot_live_graph)

        elif self.mode == 'test':
            self.hist_df = pd.DataFrame()
        else:
            print('Weird!')
    def __init__(self):

        # Period over which calculations will be made
        self.PERIOD = 20

        # Display header
        display_header()

        # Enter asset
        self.symbol = enter_data()

        self.counter = 0

        self.buy_price = 0

        # Setup Plot
        plt.style.use('seaborn')
        self.fig, self.ax = plt.subplots()

        # Account references
        self.__orders = Orders()
        self.__account = Account()
        self.__market = Market()

        # Dataframe to store data
        self.df = pd.DataFrame()

        # Qty to purchase
        self.QTY = 3000

        # Tracks position status
        self.in_position = False

        # Tracks the close prices
        self.closes = []

        # Init websocket
        self.ws = WebSocket(self)

        # Setup the plot's process
        self.p = Process(target=self.plot_live_graph)
Beispiel #5
0
class MoneyFlowIndex(IAlgorithm):
    def ws_open(self, ws):
        self.ws.on_open(ws)

        # Stream minute bars
        self.ws.stream_minute_bars(self.symbol)

    def ws_close(self, ws):
        self.ws.on_close(ws)

        # Delete csv file
        file_manager.delete_file('temp_files/{}.csv'.format(self.symbol))

        # Close plot's process if alive
        if self.p is not None:
            self.p.terminate()
            self.p.join()

    def ws_message(self, ws, message):
        # Liquidate position if market is closing soon
        if self.__market.is_market_closing():
            self.close_position_before_market_close()

            # Close graphs
            if self.p is not None:
                self.p.terminate()
                self.p.join()

            return

        # Convert retrieved data to python dict
        message = json.loads(message)

        self.ws.on_message(ws, message)

        # Get the required data: close price, high, low, volume, time
        bar_data = message['data']
        close_price = round(bar_data['c'], 2)
        close_time = datetime.fromtimestamp(int(str(
            bar_data['e'])[:-3])).strftime("%H:%M")
        high_price = round(bar_data['h'], 2)
        low_price = round(bar_data['l'], 2)
        volume = bar_data['v']

        print(self.df[-14:])

        # Calc MFI
        mfi = self.calc_mfi(self.df[-14:])
        # New Entry
        new_entry = {
            'Date': close_time,
            'Close': close_price,
            'High': high_price,
            'Low': low_price,
            'Volume': volume,
            'buy_signal': np.nan,
            'sell_signal': np.nan,
            'MFI': mfi
        }

        # Get buy or sell signal
        self.buy_sell(new_entry)

        # Add Entry to file
        new_entry_str = '{},{},{},{},{},{},{},{}'.format(
            close_time, close_price, new_entry['High'], new_entry['Low'],
            new_entry['Volume'], new_entry['buy_signal'],
            new_entry['sell_signal'], mfi)

        # Add entry to file
        file_manager.append_to_file('temp_files/{}.csv'.format(self.symbol),
                                    new_entry_str)

        # Add entry to dataframe
        self.df = self.df.append(new_entry, ignore_index=True)

        # Print retrieved data + MFI
        print('{}\t{}\tMFI: {}'.format(close_time, close_price, mfi))

    def __init__(self, mode):

        # In case of any errors
        self.error = False

        # Display Header
        display_header()

        # Bot mode
        self.mode = mode

        # Constants
        self.PERIOD = 14
        self.HIGH = 80
        self.LOW = 20
        self.MFI_MARGIN = 3

        # Assign variables
        self.symbol = enter_data()

        if self.mode == 'active':
            # Setup Plot
            plt.style.use('seaborn')
            self.fig, (self.ax1, self.ax2) = plt.subplots(2, 1)

            # Account references
            self.__orders = Orders()
            self.__account = Account()
            self.__market = Market()

            # Dataframe to store data
            self.df = pd.DataFrame()

            # Qty to purchase
            self.QTY = 1000

            # Tracks position status
            self.in_position = False

            # Keeps track of the buying price
            self.buy_price = 0

            # Init websocket
            self.ws = WebSocket(self)

            # Setup the plot's process
            self.p = Process(target=self.plot_live_graph)

        elif self.mode == 'test':
            self.hist_df = pd.DataFrame()
            self.mfi = None

    def retrieve_data(self):

        print("[Requesting Data]")

        # Create a csv file
        csv_file = CSVReadWrite("temp_files/{}.csv".format(self.symbol),
                                "Date,Close,High,Low,Volume")

        if self.mode == 'active':
            bars_dict = bars.get_historical_data(self.symbol, 100, '1Min')
            if bars_dict:
                csv_file.write_file(bars_dict, 't', 'c', 'h', 'l', 'v')

                self.df = pd.read_csv('temp_files/{}.csv'.format(self.symbol))
                self.df = self.df.set_index(
                    pd.DatetimeIndex(self.df['Date'].values).strftime("%H:%M"))
                self.df['buy_signal'] = np.nan
                self.df['sell_signal'] = np.nan

        elif self.mode == 'test':
            bars_dict = bars.get_historical_data(self.symbol, 500, 'day')
            if bars_dict:
                csv_file.write_file(bars_dict, 't', 'c', 'h', 'l', 'v')

                # Get the data
                self.hist_df = pd.read_csv("temp_files/{}.csv".format(
                    self.symbol))
                self.hist_df = self.hist_df.set_index(
                    pd.DatetimeIndex(
                        self.hist_df['Date'].values).strftime("%Y:%m:%d"))

    def calc_mfi(self, data):

        # Calc typical price
        typical_price = (data['High'] + data['Low'] + data['Close']) / 3

        # Calc Raw Money flow
        raw_money_flow = typical_price * data['Volume']

        # Store the flows
        positive_flows = []
        negative_flows = []

        # Calculate the (+) and (-) money flows
        for i in range(1, len(typical_price)):

            if typical_price[i] > typical_price[i - 1]:
                positive_flows.append(raw_money_flow[i - 1])
                negative_flows.append(0)
            elif typical_price[i] < typical_price[i - 1]:
                positive_flows.append(0)
                negative_flows.append(raw_money_flow[i - 1])
            else:
                positive_flows.append(0)
                negative_flows.append(0)

        # Sum them up
        positive_flows_sum = sum(positive_flows)
        negative_flows_sum = sum(negative_flows)

        # Money Flow Ratio
        mfr = positive_flows_sum / negative_flows_sum

        # Calculate the Money Flow Index
        money_flow_index = 100 - (100 / (1 + mfr))

        return money_flow_index

    def pre_calculate(self, data):

        # Calc typical price
        typical_price = (data['High'] + data['Low'] + data['Close']) / 3

        # Calc Raw Money Flows
        rmf = typical_price * data['Volume']

        # Calc + and - flows
        positive_flows = []
        negative_flows = []

        for i in range(1, len(typical_price)):
            if typical_price[i] > typical_price[i - 1]:
                positive_flows.append(rmf[i - 1])
                negative_flows.append(0)
            elif typical_price[i] < typical_price[i - 1]:
                positive_flows.append(0)
                negative_flows.append(rmf[i - 1])
            else:
                positive_flows.append(0)
                negative_flows.append(0)

        # Calc the sums of money flows within the time period
        positive_mf_sum = []
        negative_mf_sum = []

        for i in range(self.PERIOD - 1, len(positive_flows)):
            positive_mf_sum.append(
                sum(positive_flows[i + 1 - self.PERIOD:i + 1]))

        for i in range(self.PERIOD - 1, len(negative_flows)):
            negative_mf_sum.append(
                sum(negative_flows[i + 1 - self.PERIOD:i + 1]))

        self.mfi = 100 * (
            np.array(positive_mf_sum) /
            (np.array(negative_mf_sum) + np.array(positive_mf_sum)))

        data['MFI'] = np.nan
        data['MFI'][14:] = self.mfi

        data.to_csv(r'temp_files/{}.csv'.format(self.symbol), index=False)

    def buy_sell(self, data):

        if data['MFI'] > self.HIGH - self.MFI_MARGIN:
            # Sell
            if self.in_position:
                if self.buy_price <= data['Close']:
                    # Submit order
                    t = Thread(target=self.__orders.submit_order,
                               args=[self.symbol, self.QTY, 'sell'])
                    t.start()

                    # Change position status
                    self.in_position = False

                    # Add sell signal
                    data['sell_signal'] = data['Close']

                    # Reset buy price
                    self.buy_price = 0

                    # Wait for order to finish
                    t.join()
                else:
                    print('We bought at a higher price. Can\'t sell now.')
            else:
                print('Sell signal generated. No asset to sell.')

        elif data['MFI'] < self.LOW + self.MFI_MARGIN:
            # Buy
            if not self.in_position:
                # Submit order
                t = Thread(target=self.__orders.submit_order,
                           args=[self.symbol, self.QTY, 'buy'])
                t.start()

                # Change position status
                self.in_position = True

                # Set buying price
                self.buy_price = data['Close']

                # Add buy signal
                data['buy_signal'] = data['Close']

                # Wait for order to finish
                t.join()
            else:
                print('Buy signal generated. Already in position.')

    def close_position_before_market_close(self):
        # Close position
        print("Market closing soon.")

        # Liquidate
        self.liquidate_position()

        print("[EXITING]")

    def liquidate_position(self):
        has_position = self.__account.has_position(self.symbol)

        if has_position[0]:
            print("[Liquidating]")

            side = 'sell'
            qty = abs(int(float(has_position[1].qty)))

            t = Thread(target=self.__orders.submit_order,
                       args=[self.symbol, qty, side])
            t.start()
            t.join()

    def buy_sell_historical(self, data):
        # Store buy and sell signals
        buy_signal = []
        sell_signal = []

        for i in range(len(data['MFI'])):

            if data['MFI'][i] > self.HIGH - self.MFI_MARGIN:
                buy_signal.append(np.nan)
                sell_signal.append(data['Close'][i])
            elif data['MFI'][i] < self.LOW + self.MFI_MARGIN:
                buy_signal.append(data['Close'][i])
                sell_signal.append(np.nan)
            else:
                buy_signal.append(np.nan)
                sell_signal.append(np.nan)

        return buy_signal, sell_signal

    def plot_hist_graph(self, data):
        print('[Drawing Graph]')

        plt.style.use("fivethirtyeight")
        fig, (ax1, ax2) = plt.subplots(2, 1)

        fig.suptitle('Money Flow Index')

        # Remove x ticks
        ax1.xaxis.set_ticks([])
        ax2.xaxis.set_ticks([])

        # Set labels for axis
        ax1.set_ylabel('{} price in $ (USD)'.format(self.symbol))
        ax2.set_ylabel('MFI Values')

        # Remove grids
        ax1.grid(False)
        ax2.grid(False)

        # Disable the top and right axis
        ax1.spines['top'].set_visible(False)
        ax1.spines['right'].set_visible(False)
        ax2.spines['top'].set_visible(False)
        ax2.spines['right'].set_visible(False)

        # Change the color of the left and bottom axis
        ax1.spines['bottom'].set_color('gray')
        ax1.spines['left'].set_color('gray')
        ax2.spines['bottom'].set_color('white')
        ax2.spines['left'].set_color('white')

        # Plot prices and MFI
        ax1.plot(data.index,
                 data['Close'],
                 color='black',
                 label="Close Price",
                 alpha=0.5,
                 lw=2)
        ax2.plot(data.index, data['MFI'], label='MFI', lw=2)

        # Draw buy and sell signals
        ax1.scatter(data.index,
                    data['Buy'],
                    color="green",
                    label="Buy Signal",
                    marker="^",
                    alpha=1)
        ax1.scatter(data.index,
                    data['Sell'],
                    color="red",
                    label="Sell signal",
                    marker="v",
                    alpha=1)

        # Draw limit lines
        ax2.axhline(10, color='red', linestyle='--', linewidth=2)
        ax2.axhline(20, color='green', linestyle='--', linewidth=2)
        ax2.axhline(80, color='green', linestyle='--', linewidth=2)
        ax2.axhline(90, color='red', linestyle='--', linewidth=2)
        ax2.axhline(y=(self.LOW + self.MFI_MARGIN),
                    color='brown',
                    linestyle='--',
                    linewidth=1)
        ax2.axhline(y=(self.HIGH - self.MFI_MARGIN),
                    color='brown',
                    linestyle='--',
                    linewidth=1)

        # Show legend
        ax1.legend(loc='upper left')

        # Shot plot
        plt.show()

    def plot_live_graph(self):
        self.fig.suptitle('Price of {} over time'.format(self.symbol))

        ani = animation.FuncAnimation(self.fig, self.animate_graph)
        plt.show()

    def animate_graph(self, i):
        # Read file
        file_df = pd.read_csv('temp_files/{}.csv'.format(self.symbol))

        # Clear and plot
        self.ax1.clear()
        self.ax2.clear()
        self.ax1.plot(file_df['Date'],
                      file_df['Close'],
                      color='orange',
                      lw=3,
                      alpha=0.7)
        self.ax2.plot(file_df['Date'],
                      file_df['MFI'],
                      color='black',
                      lw=3,
                      alpha=1.0)

        # Draw buy and sell signals
        self.ax1.scatter(file_df['Date'],
                         file_df['buy_signal'],
                         color='green',
                         alpha=1.0,
                         marker='^')
        self.ax1.scatter(file_df['Date'],
                         file_df['sell_signal'],
                         color='red',
                         alpha=1.0,
                         marker='v')

        # Draw horizontal limit lines
        self.ax2.axhline(y=self.HIGH, color='red', linestyle='--')
        self.ax2.axhline(y=self.LOW, color='green', linestyle='--')
        self.ax2.axhline(y=(self.HIGH - self.MFI_MARGIN),
                         color='brown',
                         linestyle='--')
        self.ax2.axhline(y=(self.LOW + self.MFI_MARGIN),
                         color='brown',
                         linestyle='--')

        # Remove x ticks
        self.ax1.set_xticks([])
        self.ax2.set_xticks([])

        # Remove grids
        self.ax1.grid(False)
        self.ax2.grid(False)

        # Set labels
        self.ax1.set_ylabel("Price of {} in $".format(self.symbol))
        self.ax2.set_xlabel("Time")
        self.ax2.set_ylabel('MFI Values')

    def execute(self):

        if self.error:
            return

        if self.mode == 'active':
            # Cancel existing orders
            self.__orders.cancel_opened_orders()

            # Liquidate position if it exists
            self.liquidate_position()

            # Wait for market to open
            t = Thread(target=self.__market.await_market_open)
            t.start()
            t.join()
            print("[Market Opened]")

            # Retrieve historical data about the asset
            self.retrieve_data()

            # Calculate parameters
            self.pre_calculate(self.df)

            # Run socket in a thread
            t_socket = Thread(target=self.ws.connect_socket)
            t_socket.start()

            # # Run the plot's process
            # self.p.start()

            # Wait for socket to finish
            t_socket.join()

        elif self.mode == 'test':

            # Retrieve historical data
            self.retrieve_data()

            # Calculate metrics
            self.pre_calculate(self.hist_df)

            # Get buy and sell signals
            self.hist_df = self.hist_df[self.PERIOD:]
            self.hist_df['MFI'] = self.mfi
            self.hist_df['Buy'] = self.buy_sell_historical(self.hist_df)[0]
            self.hist_df['Sell'] = self.buy_sell_historical(self.hist_df)[1]

            # Plot historical graph
            self.plot_hist_graph(self.hist_df)

        # Delete the file
        file_manager.delete_file('{}.csv'.format(self.symbol), True)
class BollingerBands(IAlgorithm):
    def ws_open(self, ws):
        self.ws.on_open(ws)

        # Get the last 20 prices
        self.closes = list(self.df['Close'][-20:])

        # Stream minute bars
        self.ws.stream_minute_bars(self.symbol)

    def ws_close(self, ws):
        self.ws.on_close(ws)

        # Delete csv file
        file_manager.delete_file('temp_files/{}.csv'.format(self.symbol))

        # Terminate process if still running
        if self.p is not None:
            self.p.terminate()
            self.p.join()

    def ws_message(self, ws, message):

        # Liquidate position
        if self.__market.is_market_closing():
            self.close_position_before_market_close()

            # Close graphs
            if self.p is not None:
                self.p.terminate()
                self.p.join()

            return

        # Convert data to python dict
        message = json.loads(message)

        self.ws.on_message(ws, message)

        # Get the required data: close price, date
        bar_data = message['data']
        close_price = bar_data['c']
        close_time = datetime.fromtimestamp(int(str(
            bar_data['e'])[:-3])).strftime("%H:%M")

        # Add the received price in the list
        self.closes.append(close_price)

        # Calc metrics
        sma = self.calc_metrics()[0]
        std = self.calc_metrics()[1]
        upper = self.calc_metrics()[2]
        lower = self.calc_metrics()[3]

        # New entry
        new_entry = {
            'Date': close_time,
            'Close': close_price,
            'SMA': sma,
            'STD': std,
            'Upper': upper,
            'Lower': lower,
            'buy_signal': np.nan,
            'sell_signal': np.nan
        }

        # Get signal
        self.buy_sell(new_entry)

        # Add entry to file
        new_entry_str = '\n{},{},{},{},{},{},{},{}'.format(
            close_time, close_price, new_entry['buy_signal'],
            new_entry['sell_signal'], new_entry['SMA'], new_entry['STD'],
            new_entry['Upper'], new_entry['Lower'])
        file_manager.append_to_file('temp_files/{}.csv'.format(self.symbol),
                                    new_entry_str)

        # Add entry to dataframe
        self.df = self.df.append(new_entry, ignore_index=True)

        # Print data on the screen
        print('{}\t{}\tUpper band: {}\tLower band: {}'.format(
            close_time, close_price, new_entry['Upper'], new_entry['Lower']))

    def calc_metrics(self):
        closes = self.closes[-20:]

        # Calc the STD
        sma = sum(closes) / self.PERIOD
        std = self.std(closes, sma)

        # Calc Upper band and lower band
        upper = sma + (2 * std)
        lower = sma - (2 * std)

        return sma, std, upper, lower

    def std(self, data, mean):

        # Square deviations
        deviations = [(x - mean)**2 for x in data]

        # Variance
        variance = sum(deviations) / self.PERIOD

        return math.sqrt(variance)

    def __init__(self, mode):

        # Set bot mode
        self.mode = mode

        # In case something goes wrong
        self.error = False

        # Period over which calculations will be made
        self.PERIOD = 20

        # Display header
        display_header()

        # Enter asset
        self.symbol = enter_data()

        if self.mode == 'active':
            # Setup Plot
            plt.style.use('seaborn')
            self.fig, self.ax = plt.subplots()

            # Account references
            self.__orders = Orders()
            self.__account = Account()
            self.__market = Market()

            # Dataframe to store data
            self.df = pd.DataFrame()

            # Qty to purchase
            self.QTY = 1000

            # Track buy price
            self.buy_price = 0

            # Tracks position status
            self.in_position = False

            # Tracks the close prices
            self.closes = []

            # Init websocket
            self.ws = WebSocket(self)

            # Setup the plot's process
            self.p = Process(target=self.plot_live_graph)

        elif self.mode == 'test':
            # self.position = False
            self.hist_df = pd.DataFrame()

    def retrieve_data(self):

        # In case no error, write data to a file
        csv_file = CSVReadWrite("temp_files/{}.csv".format(self.symbol),
                                "Date,Close")

        if self.mode == 'active':
            bars_dict = bars.get_historical_data(self.symbol, 100, '1Min')
            if bars_dict:
                csv_file.write_file(bars_dict, 't', 'c')
                self.df = pd.read_csv('temp_files/{}.csv'.format(self.symbol))
                self.df = self.df.set_index(
                    pd.DatetimeIndex(self.df['Date'].values).strftime("%H:%M"))
                self.df['buy_signal'] = np.nan
                self.df['sell_signal'] = np.nan
            else:
                self.error = True
        else:
            bars_dict = bars.get_historical_data(self.symbol, 500, 'day')

            if bars_dict:
                csv_file.write_file(bars_dict, 't', 'c')
                self.hist_df = pd.read_csv('temp_files/{}.csv'.format(
                    self.symbol))
                self.hist_df = self.hist_df.set_index(
                    pd.DatetimeIndex(
                        self.hist_df['Date'].values).strftime("%Y:%m:%d"))
            else:
                self.error = True

    def pre_calculate(self, data):

        # Calculate the Simple Moving Average
        data['SMA'] = data['Close'].rolling(window=self.PERIOD).mean()

        # Calculate the standard deviation
        data['STD'] = data['Close'].rolling(window=self.PERIOD).std()

        # Calculate the upper bands and the lower bands
        data['Upper'] = data['SMA'] + (2 * data['STD'])
        data['Lower'] = data['SMA'] - (2 * data['STD'])

        # Write to file
        data.to_csv(r'temp_files/{}.csv'.format(self.symbol), index=False)

    def buy_sell(self, data):

        if data['Close'] > data['Upper']:
            # Sell!
            print('Sell signal!')
            if self.in_position:
                if self.buy_price <= data['Close']:
                    # Run thread to submit order
                    t = Thread(target=self.__orders.submit_order,
                               args=[self.symbol, self.QTY, 'sell'])
                    t.start()

                    # Change position status
                    self.in_position = False

                    # Reset buy price
                    self.buy_price = 0

                    # Add sell signal
                    data['sell_signal'] = data['Close']

                    # Wait for order to finish
                    t.join()
                else:
                    print('We bought at a higher price. Can\'t sell now.')
            else:
                print('Nothing to sell.')
        elif data['Close'] < data['Lower']:
            # Buy
            print('Buy signal!')
            if not self.in_position:
                # Run thread to submit order
                t = Thread(target=self.__orders.submit_order,
                           args=[self.symbol, self.QTY, 'buy'])
                t.start()

                # Change position status
                self.in_position = True

                # Set buy price
                self.buy_price = data['Close']

                # Add buy signal
                data['buy_signal'] = data['Close']

                # Wait for order to finish
                t.join()
            else:
                print('Already in position.')

    def buy_sell_historical(self, data):

        buy_signal = []
        sell_signal = []

        for i in range(len(data['Close'])):
            if data['Close'][i] >= data['Upper'][i]:
                # Sell
                buy_signal.append(np.nan)
                sell_signal.append(data['Close'][i])
            elif data['Close'][i] <= data['Lower'][i]:
                # Buy
                buy_signal.append(data['Close'][i])
                sell_signal.append(np.nan)
            else:
                # Do nothing
                buy_signal.append(np.nan)
                sell_signal.append(np.nan)

        return buy_signal, sell_signal

    def close_position_before_market_close(self):

        # Close position
        print("Market closing soon.")

        # Liquidate
        self.liquidate_position()

        print("[EXITING]")

    def liquidate_position(self):
        has_position = self.__account.has_position(self.symbol)

        if has_position[0]:
            print("[Liquidating].")
            side = 'sell'

            qty = abs(int(float(has_position[1].qty)))

            t_submit_order = Thread(target=self.__orders.submit_order,
                                    args=[self.symbol, qty, side])

            t_submit_order.start()
            t_submit_order.join()

    def plot_hist_graph(self, data):
        plt.style.use('fivethirtyeight')
        fig = plt.figure(figsize=(12.2, 6.4), facecolor='white')

        # Add the subplot
        ax = fig.add_subplot(111)

        ax.xaxis.set_ticks([])

        # Change the color of the left and bottom axis
        ax.spines['bottom'].set_color('gray')
        ax.spines['left'].set_color('gray')

        # Get the index values
        x_axis = data.index

        # Remove grid
        ax.grid(False)

        # Disable the top and right axis
        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)

        # Plot the bands
        ax.plot(x_axis,
                data['Upper'],
                color='brown',
                lw=1,
                label='Upper',
                alpha=0.5)
        ax.plot(x_axis,
                data['Lower'],
                color='brown',
                lw=1,
                label='Lower',
                alpha=0.5)

        # Plot the closing price and the moving average
        ax.plot(x_axis,
                data['Close'],
                color='black',
                lw=3,
                label='Close Price',
                alpha=0.5)
        ax.plot(x_axis,
                data['SMA'],
                color='blue',
                lw=1,
                label='Simple Moving Average')

        # Add the buy and sell signals
        ax.scatter(x_axis,
                   data['Buy'],
                   label='Buy',
                   alpha=1,
                   color='green',
                   marker='^')
        ax.scatter(x_axis,
                   data['Sell'],
                   label='Sell',
                   alpha=1,
                   color='red',
                   marker='v')

        # Set the title and show the plot
        ax.set_title("Bollinger Bands for {}".format(self.symbol),
                     color='black')
        ax.set_ylabel('USD Price ($)', color='black')
        ax.set_xlabel('Time', color='black')
        plt.xticks(rotation=45, fontsize=7)
        ax.legend(loc='upper left', framealpha=0.2, fancybox=True)
        plt.show()

    def plot_live_graph(self):
        self.fig.suptitle("Price of {} over time".format(self.symbol))

        ani = animation.FuncAnimation(self.fig, self.animate_graph)
        plt.show()

    def animate_graph(self, i):

        # Read file
        file_df = pd.read_csv('temp_files/{}.csv'.format(self.symbol))

        # Clear and plot
        self.ax.clear()
        self.ax.plot(file_df['Date'], file_df['Close'], linewidth=3)
        self.ax.plot(file_df['Date'], file_df['Upper'], linewidth=1)
        self.ax.plot(file_df['Date'], file_df['Lower'], linewidth=1)
        self.ax.plot(file_df['Date'], file_df['SMA'], linewidth=1)

        # Draw buy and sell signals
        self.ax.scatter(file_df['Date'],
                        file_df['buy_signal'],
                        marker='^',
                        color='green',
                        alpha=1.0)
        self.ax.scatter(file_df['Date'],
                        file_df['sell_signal'],
                        marker='v',
                        color='red',
                        alpha=1.0)

        # Set labels
        self.ax.set_ylabel("Price of {} in $".format(self.symbol))
        self.ax.xaxis.set_ticks([])

    def execute(self):
        if self.error:
            print('Error occurred')
            return

        if self.mode == 'active':
            # Cancel existing orders
            self.__orders.cancel_opened_orders()

            # Liquidate position if it exists
            self.liquidate_position()

            # Wait for market to open
            t = Thread(target=self.__market.await_market_open)
            t.start()
            t.join()
            print("[Market Opened]")

            # Retrieve historical data about the asset
            self.retrieve_data()

            # Calculate parameters
            self.pre_calculate(self.df)

            # Run the web socket
            t_socket = Thread(target=self.ws.connect_socket)
            t_socket.start()

            # Run the plot's process
            self.p.start()

            # Wait for thread to finish work
            t_socket.join()

        elif self.mode == 'test':

            # Retrieve historical data
            self.retrieve_data()

            # Calculate metrics
            self.pre_calculate(self.hist_df)

            # Get buy and sell signals
            self.hist_df = self.hist_df[self.PERIOD - 1:]
            self.hist_df['Buy'] = self.buy_sell_historical(self.hist_df)[0]
            self.hist_df['Sell'] = self.buy_sell_historical(self.hist_df)[1]

            # Plot the graph
            self.plot_hist_graph(self.hist_df)

        # Delete csv file
        file_manager.delete_file('{}.csv'.format(self.symbol), True)
class BollingerBands(IAlgorithm):

    def ws_open(self, ws):
        self.ws.on_open(ws)

        # Stream minute bars
        self.ws.stream_trades(self.symbol)

    def ws_close(self, ws):
        self.ws.on_close(ws)

        # Delete csv file
        file_manager.delete_file('temp_files/{}.csv'.format(self.symbol))

        # Terminate process if still running
        if self.p is not None:
            self.p.terminate()
            self.p.join()

    def ws_message(self, ws, message):

        # Liquidate position
        if self.__market.is_market_closing():
            self.close_position_before_market_close()

            # Close graphs
            if self.p is not None:
                self.p.terminate()
                self.p.join()

            return

        # Convert data to python dict
        message = json.loads(message)

        self.ws.on_message(ws, message)

        # Get the required data: close price
        bar_data = message['data']
        close_price = bar_data['p']
        self.counter += 1

        # Add the received price in the list
        self.closes.append(close_price)

        # Calc metrics
        sma = self.calc_metrics()[0]
        std = self.calc_metrics()[1]
        upper = self.calc_metrics()[2]
        lower = self.calc_metrics()[3]

        if sma == 0 or std == 0 or upper == 0 or lower == 0:
            pass
        else:
            # New entry
            new_entry = {
                'Date': self.counter,
                'Close': close_price,
                'SMA': sma,
                'STD': std,
                'Upper': upper,
                'Lower': lower,
                'buy_signal': np.nan,
                'sell_signal': np.nan
            }

            # Get signal
            self.buy_sell(new_entry)

            # Add entry to file
            new_entry_str = '{},{},{},{},{},{},{},{}'.format(
                self.counter, close_price,
                new_entry['buy_signal'], new_entry['sell_signal'],
                new_entry['SMA'], new_entry['STD'],
                new_entry['Upper'], new_entry['Lower']
            )
            file_manager.append_to_file('temp_files/{}.csv'.format(self.symbol), new_entry_str)

            # Add entry to dataframe
            self.df = self.df.append(new_entry, ignore_index=True)

            # Print data on the screen
            print('{}\tPrice: ${}\tUpper band: {}\tLower band: {}'.format(
                self.counter, close_price,
                new_entry['Upper'], new_entry['Lower']
            ))

    def calc_metrics(self):
        if len(self.closes) > 20:
            closes = self.closes[-20:]

            # Calc the STD
            sma = sum(closes) / self.PERIOD
            std = self.std(closes, sma)

            # Calc Upper band and lower band
            upper = sma + (2 * std)
            lower = sma - (2 * std)

            return sma, std, upper, lower
        else:
            return 0, 0, 0, 0

    def std(self, data, mean):

        # Square deviations
        deviations = [(x - mean) ** 2 for x in data]

        # Variance
        variance = sum(deviations) / self.PERIOD

        return math.sqrt(variance)

    def __init__(self):

        # Period over which calculations will be made
        self.PERIOD = 20

        # Display header
        display_header()

        # Enter asset
        self.symbol = enter_data()

        self.counter = 0

        self.buy_price = 0

        # Setup Plot
        plt.style.use('seaborn')
        self.fig, self.ax = plt.subplots()

        # Account references
        self.__orders = Orders()
        self.__account = Account()
        self.__market = Market()

        # Dataframe to store data
        self.df = pd.DataFrame()

        # Qty to purchase
        self.QTY = 3000

        # Tracks position status
        self.in_position = False

        # Tracks the close prices
        self.closes = []

        # Init websocket
        self.ws = WebSocket(self)

        # Setup the plot's process
        self.p = Process(target=self.plot_live_graph)

    def buy_sell(self, data):

        if data['Close'] > data['Upper']:
            # Sell!
            print('Sell signal!')
            if self.in_position:
                if data['Close'] - self.buy_price >= 0:
                    # Run thread to submit order
                    t = Thread(target=self.__orders.submit_order, args=[self.symbol, self.QTY, 'sell'])
                    t.start()

                    # Change position status
                    self.in_position = False

                    # Reset previous buy price
                    self.buy_price = 0

                    # Add sell signal
                    data['sell_signal'] = data['Close']

                    t.join()
                else:
                    print('Can\'t sell now. We bought at a higher price.')
            else:
                print('Nothing to sell.')
        elif data['Close'] < data['Lower']:
            # Buy
            print('Buy signal!')
            if not self.in_position:
                # Run thread to submit order
                t = Thread(target=self.__orders.submit_order, args=[self.symbol, self.QTY, 'buy'])
                t.start()

                # Change position status
                self.in_position = True

                # Set the previous buy price
                self.buy_price = data['Close']

                # Add buy signal
                data['buy_signal'] = data['Close']

                t.join()
            else:
                print('Already in position.')

    def close_position_before_market_close(self):

        # Close position
        print("Market closing soon.")

        # Liquidate
        self.liquidate_position()

        print("[EXITING]")

    def liquidate_position(self):
        has_position = self.__account.has_position(self.symbol)

        if has_position[0]:
            print("[Liquidating].")
            side = 'sell'

            qty = abs(int(float(has_position[1].qty)))

            t_submit_order = Thread(target=self.__orders.submit_order,
                                    args=[self.symbol, qty, side])

            t_submit_order.start()
            t_submit_order.join()

    def plot_live_graph(self):
        self.fig.suptitle("Price of {} over time".format(self.symbol))

        ani = animation.FuncAnimation(self.fig, self.animate_graph)
        plt.show()

    def animate_graph(self, i):

        # Read file
        file_df = pd.read_csv('temp_files/{}.csv'.format(self.symbol))
        if not file_df.empty:
            # Clear and plot
            self.ax.clear()
            self.ax.plot(file_df['Date'], file_df['Close'], alpha=0.5, linewidth=3)
            self.ax.plot(file_df['Date'], file_df['Upper'], alpha=0.5, linewidth=1)
            self.ax.plot(file_df['Date'], file_df['Lower'], alpha=0.5, linewidth=1)
            self.ax.plot(file_df['Date'], file_df['SMA'], alpha=0.5, linewidth=1)

            # Draw buy and sell signals
            self.ax.scatter(file_df['Date'], file_df['buy_signal'], marker='^', color='green', alpha=1.0)
            self.ax.scatter(file_df['Date'], file_df['sell_signal'], marker='v', color='red', alpha=1.0)

            # Set labels
            self.ax.set_ylabel("Price of {} in $".format(self.symbol))
            self.ax.set_xlabel("Time")
            self.ax.tick_params(axis='x', rotation=45)
            plt.xticks(fontsize=5)

    def execute(self):

        # Cancel existing orders
        self.__orders.cancel_opened_orders()

        # Liquidate position if it exists
        self.liquidate_position()

        # Wait for market to open
        t = Thread(target=self.__market.await_market_open)
        t.start()
        t.join()
        print("[Market Opened]")

        # Setup file
        file = open('temp_files/{}.csv'.format(self.symbol), 'w')
        file.write('Date,Close,buy_signal,sell_signal,SMA,STD,Upper,Lower\n')
        file.close()

        # Run the web socket
        t_socket = Thread(target=self.ws.connect_socket)
        t_socket.start()

        # Run the plot's process
        self.p.start()

        # Wait for thread to finish work
        t_socket.join()

        # Delete file
        file_manager.delete_file('SPY.csv'.format(self.symbol), True)
Beispiel #8
0
class DualAverageCrossover(IAlgorithm):
    def ws_open(self, ws):
        self.ws.on_open(ws)

        # Get the last 100 prices
        self.closes = list(self.df['Close'])[-100:]

        # Stream minute bars
        self.ws.stream_minute_bars(self.symbol)

    def ws_close(self, ws):
        self.ws.on_close(ws)

        # Delete csv file
        file_manager.delete_file('temp_files/{}.csv'.format(self.symbol))

        # Terminate process if still running
        if self.p is not None:
            self.p.terminate()
            self.p.join()

    def ws_message(self, ws, message):
        # Liquidate position
        if self.__market.is_market_closing():
            self.close_position_before_market_close()

            # Close graphs
            if self.p is not None:
                self.p.terminate()
                self.p.join()

            return

        # Convert data to python dict
        message = json.loads(message)

        self.ws.on_message(ws, message)

        # Get the required data: time, close price
        bar_data = message['data']
        close_price = bar_data['c']
        close_time = datetime.fromtimestamp(int(str(
            bar_data['e'])[:-3])).strftime("%H:%M")

        # Add the received price in the list
        self.closes.append(close_price)

        # Calc metrics
        sma30 = self.calc_metrics()[0]
        sma100 = self.calc_metrics()[1]

        # New Entry
        new_entry = {
            'Date': close_time,
            'Close': close_price,
            'SMA30': sma30,
            'SMA100': sma100,
            'buy_signal': np.nan,
            'sell_signal': np.nan
        }

        # Get Signal
        self.buy_sell(new_entry)

        # Add Entry to file
        new_entry_str = '{},{},{},{},{},{}  '.format(close_time, close_price,
                                                     new_entry['buy_signal'],
                                                     new_entry['sell_signal'],
                                                     sma30, sma100)
        file_manager.append_to_file('temp_files/{}.csv'.format(self.symbol),
                                    new_entry_str)

        # Add entry to dataframe
        self.df = self.df.append(new_entry, ignore_index=True)

        # Print data on the screen
        print('{}\tPrice: {}\tSMA30: {}\tSMA100: {}'.format(
            close_time, close_price, new_entry['SMA30'], new_entry['SMA100']))

    def calc_metrics(self):
        closes = self.closes[-100:]

        sma30 = sum(closes[-30:]) / 30
        sma100 = sum(closes) / 100

        return sma30, sma100

    def __init__(self, mode):

        # In case of any error
        self.error = False

        # Bot mode
        self.mode = mode

        # Display Header
        display_header()

        self.symbol = enter_data()

        if self.mode == 'active':
            # Setup Plot
            plt.style.use('seaborn')
            self.fig, self.ax = plt.subplots()

            # Account references
            self.__orders = Orders()
            self.__account = Account()
            self.__market = Market()

            # Dataframe to store data
            self.df = pd.DataFrame()

            # Qty to purchase
            self.QTY = 50

            # Tracks position status
            self.in_position = False

            # Tracks the close prices
            self.closes = []

            # Init websocket
            self.ws = WebSocket(self)

            # Track buy price
            self.buy_price = 0

            # Setup the plot's process
            self.p = Process(target=self.plot_live_graph)

        elif self.mode == 'test':
            self.hist_df = pd.DataFrame()
        else:
            print('Weird!')

    def retrieve_data(self):
        # Retrieve bars from API
        print("[Requesting Data]")

        # Create CSV File
        csv_file = CSVReadWrite("temp_files/{}.csv".format(self.symbol),
                                "Date,Close")

        if self.mode == 'active':

            bars_dict = bars.get_historical_data(self.symbol, 200, '1Min')

            if bars_dict:
                csv_file.write_file(bars_dict, 't', 'c')
                self.df = pd.read_csv('temp_files/{}.csv'.format(self.symbol))
                self.df = self.df.set_index(
                    pd.DatetimeIndex(self.df['Date'].values).strftime("%H:%M"))
                self.df['buy_signal'] = np.nan
                self.df['sell_signal'] = np.nan
            else:
                self.error = True
        elif self.mode == 'test':
            bars_dict = bars.get_historical_data(self.symbol, 400, 'day')
            if bars_dict:
                csv_file.write_file(bars_dict, 't', 'c')
                self.hist_df = pd.read_csv('temp_files/{}.csv'.format(
                    self.symbol))
                self.hist_df = self.hist_df.set_index(
                    pd.DatetimeIndex(self.hist_df['Date'].values))
            else:
                self.error = True

    def pre_calculate(self, data):

        # Calculate SMA30
        data['SMA30'] = data['Close'].rolling(window=30).mean()

        # Calculate SMA100
        data['SMA100'] = data['Close'].rolling(window=100).mean()

        # Write to file
        data.to_csv(r'temp_files/{}.csv'.format(self.symbol), index=False)

    def buy_sell(self, data):

        if data['SMA30'] > data['SMA100']:
            # Sell
            if self.in_position:
                if self.buy_price <= data['Close']:
                    # Submit order
                    t = Thread(target=self.__orders.submit_order,
                               args=[self.symbol, self.QTY, 'sell'])
                    t.start()

                    # Change position status
                    self.in_position = False

                    # Add sell signal
                    data['sell_signal'] = data['Close']

                    # Reset buy price
                    self.buy_price = 0

                    # Wait for order to finish
                    t.join()
                else:
                    print('We bought at a higher price. Can\'t sell now.')
            else:
                print('Sell signal generated. No asset to sell.')
        elif data['SMA100'] < data['SMA30']:
            # Buy
            if not self.in_position:
                # Submit order
                t = Thread(target=self.__orders.submit_order,
                           args=[self.symbol, self.QTY, 'buy'])
                t.start()

                # Change position status
                self.in_position = True

                # Add buy signal
                data['buy_signal'] = data['Close']

                # Set buy price
                self.buy_price = data['Close']

                # Wait for order to finish
                t.join()

    def liquidate_position(self):
        has_position = self.__account.has_position(self.symbol)

        if has_position[0]:
            print("[Closing Position].")
            side = 'sell'

            qty = abs(int(float(has_position[1].qty)))

            t_submit_order = Thread(target=self.__orders.submit_order,
                                    args=[self.symbol, qty, side])

            t_submit_order.start()
            t_submit_order.join()

    def close_position_before_market_close(self):
        # Close position
        print("Market closing soon.")

        # Liquidate
        self.liquidate_position()

        print("[EXITING]")
        exit()

    def buy_sell_historical(self, data):

        print("[Executing Algo]")

        buy_signal = []
        sell_signal = []
        crossed = -1

        for i in range(len(data)):
            if data['SMA30'][i] > data['SMA100'][i]:
                if crossed != 1:
                    sell_signal.append(data['Close'][i])
                    buy_signal.append(np.nan)
                    crossed = 1
                else:
                    sell_signal.append(np.nan)
                    buy_signal.append(np.nan)

            elif data['SMA30'][i] < data['SMA100'][i] and crossed == 1:
                if crossed != 0:
                    sell_signal.append(np.nan)
                    buy_signal.append(data['Close'][i])
                    crossed = 0
                else:
                    sell_signal.append(np.nan)
                    buy_signal.append(np.nan)
            else:
                sell_signal.append(np.nan)
                buy_signal.append(np.nan)

        return buy_signal, sell_signal

    def plot_hist_graph(self, data):
        print("[Drawing Graph]")

        plt.style.use("fivethirtyeight")

        fig, ax = plt.subplots(1, 1, facecolor='black')

        fig.suptitle('Dual Moving Averages Crossover', color='white')

        # Disable the grid
        ax.grid(False)

        # Set background color and change axis values color
        ax.set_facecolor('black')
        ax.tick_params(axis='x', colors='white')
        ax.tick_params(axis='y', colors='white')

        ax.set_ylabel('{} price in $ (USD)'.format(self.symbol), color='white')

        # Disable the top and right axis
        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)

        # Change the color of the left and bottom axis
        ax.spines['left'].set_color('gray')
        ax.spines['bottom'].set_color('gray')

        # Plot asset prices
        ax.plot(data['Close'],
                label='Close Prices',
                color='orange',
                alpha=0.5,
                linewidth=2)

        # Plot SMA30 and SMA100
        ax.plot(data['SMA30'],
                label='SMA30',
                color='brown',
                alpha=0.4,
                linewidth=1)
        ax.plot(data['SMA100'],
                label='SMA100',
                color='brown',
                alpha=0.4,
                linewidth=1)

        # Draw buy and sell signals
        ax.scatter(data.index,
                   data['Buy'],
                   label='Buy',
                   marker='^',
                   color='green')
        ax.scatter(data.index,
                   data['Sell'],
                   label='Sell',
                   marker='v',
                   color='red')

        ax.legend(loc='upper left')

        plt.xticks(rotation=45, fontsize=7)
        plt.show()

    def plot_live_graph(self):
        self.fig.suptitle("Dual Moving Averages Crossover")

        ani = animation.FuncAnimation(self.fig, self.animate_graph)
        plt.show()

    def animate_graph(self, i):
        # Read file
        file_df = pd.read_csv('temp_files/{}.csv'.format(self.symbol))

        # Clear and plot
        self.ax.clear()
        self.ax.plot(file_df['Date'],
                     file_df['Close'],
                     label='Close Price',
                     color='black',
                     lw=2)
        self.ax.plot(file_df['Date'],
                     file_df['SMA30'],
                     label='SMA30',
                     color='red',
                     lw=1)
        self.ax.plot(file_df['Date'],
                     file_df['SMA100'],
                     label='SMA100',
                     color='blue',
                     lw=1)

        # Draw buy and sell signals
        self.ax.scatter(file_df['Date'],
                        file_df['buy_signal'],
                        label='Buy Signal',
                        color='green',
                        alpha=1.0,
                        marker='^')
        self.ax.scatter(file_df['Date'],
                        file_df['sell_signal'],
                        label='Sell Signal',
                        color='red',
                        alpha=1.0,
                        marker='v')

        # Remove grid
        self.ax.grid(False)

        self.ax.xaxis.set_ticks([])

        # Show the legend
        self.ax.legend(loc='upper left')

        # Set labels
        self.ax.set_ylabel('Close Price of {} in $'.format(self.symbol))

    def execute(self):

        if self.error:
            # Delete csv file
            file_manager.delete_file('temp_files/{}.csv'.format(self.symbol))
            return

        if self.mode == 'active':
            # Cancel existing orders
            self.__orders.cancel_opened_orders()

            # Liquidate position if it exists
            self.liquidate_position()

            # Wait for market to open
            t = Thread(target=self.__market.await_market_open)
            t.start()
            t.join()
            print("[Market Opened]")

            # Retrieve historical data about the asset
            self.retrieve_data()

            # Calculate metrics
            self.pre_calculate(self.df)

            # Start algo in a thread
            t_socket = Thread(target=self.ws.connect_socket)
            t_socket.start()

            # Run the plot's process
            self.p.start()

            # Wait for socket to close
            t_socket.join()

        elif self.mode == 'test':

            # Retrieve historical data
            self.retrieve_data()

            # Calculate Metrics
            self.pre_calculate(self.hist_df)

            # Get buy and sell signals
            self.hist_df = self.hist_df[99:]
            self.hist_df['Buy'] = self.buy_sell_historical(self.hist_df)[0]
            self.hist_df['Sell'] = self.buy_sell_historical(self.hist_df)[1]

            # Plot graph
            self.plot_hist_graph(self.hist_df)

        # Delete CSV File
        file_manager.delete_file('{}.csv'.format(self.symbol), True)