Example #1
0
def plot(ticker_columns):
    """
    Args:
       ticker_columns (list): Tickers and ticker  columns to plot.
          This argument must be an iterable on the format:
             [[instrument_ticker_a, column_name_a],
              [instrument_ticker_b, column_name_b],
              ...]          
    """

    # create linked_plot() arguments
    l = []
    for instrument_name, column_name in ticker_columns:
        instrument = get_instrument(instrument_name.upper())
        plot_title = instrument_name.upper() + "_" + column_name
        l.append((instrument.data, column_name, plot_title))

    # create the plot
    linked_plot(l)
Example #2
0
    def get_instrument(self, ticker):
        """
        Get an altered version of the instrument which only contains
        date up till today.

        Args:
           ticker(str): Ticker name
        
        Return:
           A deepcopied version of the Instrument object
        """
        # get a copy of the Instrument object which we can modify
        instrument = deepcopy(get_instrument(ticker))

        row_index = instrument.get_day_index(self.today)

        # delete data which is into the future and the strategy now nothing of
        instrument.data = np.delete(instrument.data, np.s_[row_index + 1:])

        return instrument
Example #3
0
    def get_value(self, date):
        """
        Get the closing value of an instrument at a given date
        The closing value will be used if it exists,
        otherwise the 'value' field will be used.
        Nasdaq OMX data typical doesn't have closing values.

        Args:
           date(datetime.date): Date to get value for

        Return:
           The monetary value of the asset
        """
        instrument = get_instrument(self.ticker)
        day_data = instrument.get_day(date)

        # preferably use the 'close' field, then the 'value' field
        try:
            current_price = day_data['close']
        except KeyError:
            current_price = day_data['value']

        return self.quantity * current_price
Example #4
0
def plot(ticker_columns):
    """
    Args:
       ticker_columns (list): Tickers and ticker  columns to plot.
          This argument must be an iterable on the format:
             [[instrument_ticker_a, column_name_a],
              [instrument_ticker_b, column_name_b],
              ...]          
    """

    linked_plot = LinkedPlot(window_title="plot_instrument.py")

    # add plots to the main window
    for instrument_name, column_name in ticker_columns:

        instrument = get_instrument(instrument_name.upper())

        # create a new plot with one subplot (data series) in it
        linked_plot.add_plot(plot_title=instrument_name.upper())
        linked_plot.add_subplot(instrument.data, y_axis_name=column_name)

    # show the GUI window
    linked_plot.show()
Example #5
0
def simulate(strategy, money, from_date, to_date):

    # share holding positions {ticker: Share,}
    portfolio = {}

    # for all trading days between the two dates
    for today in trading_days(from_date, to_date):

        # run the strategy for this date
        orders = strategy.execute(today)

        # process the orders
        for order in orders:

            # get the instrument object
            instrument = get_instrument(order.ticker)

            # the the market date for this instrument for this date
            ticker_day = instrument.get_day(today)

            # assume orders get filled at best price
            if order.action == 'buy':
                if order.price is None:
                    order.fill(ticker_day['low'])
                elif ticker_day['low'] <= order.price:
                    order.fill(ticker_day['low'])
            elif order.action == 'sell':
                if order.price is None:
                    order.fill(ticker_day['high'])
                elif ticker_day['high'] >= order.price:
                    order.fill(ticker_day['high'])
            else:
                raise Exception("Order.action is neither 'sell' nor 'buy'")

            if order.filled:
                # update the Share object if it exists for this ticker
                try:
                    share = portfolio[order.ticker]
                    new_quantity = share.quantity + order.quantity
                    share.price = ((share.quantity * share.price) + \
                                   (order.quantity * order.price)) / new_quantity
                    share.quantity = new_quantity
                except KeyError:
                    # create a new share object
                    share = Share(order.ticker, order.quantity,
                                  order.filled_price)
                    portfolio[order.ticker] = share

                money -= order.total

            interest = broker.calculate_interest(money)
            money += interest

        # calculate the current market value
        portfolio_value = money
        for share in portfolio.values():
            share_value = share.get_value(today)
            portfolio_value += share_value

        # the total value of the account
        account_value = money + portfolio_value

        loan_ratio = broker.calculate_loan_ratio(account_value,
                                                 portfolio_value)
        if loan_ratio < broker.MIN_LOAN_TO_VALUE_RATIO:
            raise Exception("Loan-to-value-ratio is too low: " +
                            str(loan_ratio))

        # print a message summary of today
        print("%s: account_value: %.0f, money: %.0f, interest: %.0f" % \
              (str(today), account_value, money, interest))
        indent = len(str(today)) + 2
        for order in orders:
            print(' ' * indent + str(order))
Example #6
0
    variance = statistics.variance(gain_ratios)
    std_deviation = statistics.stdev(gain_ratios)

    data = OrderedDict()
    data['trades'] = trades
    data['year_count'] = year_count
    data['avg_gain_ratio'] = avg_gain_ratio
    data['pos_gain_ratio'] = pos_gain_ratio
    data['variance'] = variance
    data['std_deviation'] = std_deviation
    return data


if __name__ == "__main__":

    # Parse command line arguments
    parser = argparse.ArgumentParser(
        description="Find the historical return between dates")
    parser.add_argument("ticker", help="Ticker name (ex.: OBX.OSE)")
    parser.add_argument("buy_date", help="Buy date: YYYY-MM-DD")
    parser.add_argument("sell_date", help="Sell date: YYYY-MM-DD")
    args = parser.parse_args()

    # get the instrument from the database
    instrument = get_instrument(args.ticker.upper())

    buy_date = parse_date(args.buy_date)
    sell_date = parse_date(args.sell_date)

    pprint(historical_return_from_to_date(instrument, buy_date, sell_date))
Example #7
0
def simulate(strategy, money, from_date, to_date, reference):

    # the number of shares we could have bought from the reference instrument
    reference_shares = money / reference.get_price(from_date)

    # share holding positions {ticker: Share,}
    portfolio = {}

    # log what the strategy is doing by appending tuples:
    strategy_log = []

    # info about what the strategy is doing on the format tuple(date, str)
    action_markers = []

    # for all trading days between the two dates
    for today in trading_days(from_date, to_date):

        # label text to show for this day in the plot
        action_label = None

        # run the strategy for this date
        orders = strategy.execute(today, portfolio, money)

        # process the orders
        for order in orders:

            # get the instrument object
            instrument = get_instrument(order.ticker)

            # get the market date for this instrument for this date
            try:
                ticker_day = instrument.get_day(today)
            except KeyError:
                ticker_day = None

            # assume orders get filled at average price
            average_price = instrument.get_price(today)

            # If there was no trading for this ticker on this date
            # we're going to assume that this trade wasn't filled
            if ticker_day is None:
                pass

            # try to fill orders
            elif order.action == 'buy':
                if order.price is None:
                    order.fill(average_price)
                elif average_price <= order.price:
                    order.fill(average_price)
                money -= order.total
            elif order.action == 'sell':
                if order.price is None:
                    order.fill(average_price)
                elif average_price >= order.price:
                    order.fill(average_price)
                money += order.total
            else:
                raise Exception("Order.action is neither 'sell' nor 'buy'")

            if order.filled:

                # update the action label for the plot
                if action_label is None:
                    action_label = ""
                else:
                    action_label += "\n"
                action_label += order.action + " " + \
                    order.ticker + " " + str(order.filled_price)

                # update the Share object if it exists for this ticker
                try:
                    share = portfolio[order.ticker]

                    # the new number of shares of this stock we own now
                    if order.action == 'sell':
                        new_quantity = share.quantity - order.quantity
                    else:
                        new_quantity = share.quantity + order.quantity

                        share.price = ((share.quantity * share.price) +
                                       (order.quantity * order.filled_price)) / new_quantity

                    share.quantity = new_quantity

                    if new_quantity == 0:
                        portfolio.pop(order.ticker)

                except KeyError:
                    # create a new share object
                    share = Share(order.ticker, order.quantity,
                                  order.filled_price)
                    portfolio[order.ticker] = share

        interest = broker.calculate_interest(money)
        money += interest

        # calculate the current market value
        portfolio_value = 0
        for share in portfolio.values():
            share_value = share.get_value(today)
            portfolio_value += share_value

        # the total value of the account
        account_value = money + portfolio_value

        loan_ratio = broker.calculate_loan_ratio(
            account_value, portfolio_value)
        if loan_ratio < broker.MIN_LOAN_TO_VALUE_RATIO:
            print("Loan-to-value-ratio is too low: " + str(loan_ratio))
            break

        # calculate the value of the reference shares
        reference_value = reference_shares * reference.get_price(today)

        # add an entry to the log for today
        strategy_log.append((today,
                             account_value,
                             money,
                             portfolio_value,
                             loan_ratio,
                             reference_value))

        if action_label is not None:
            action_markers.append((today, action_label))

        # print a message summary of today
        print("%s: reference_value: %.0f, account_value: %.0f, money: %.0f, interest: %.0f" %
              (str(today), reference_value, account_value, money, interest))
        indent = len(str(today)) + 2
        for order in orders:
            print(' ' * indent + str(order))

    matrix = np.array(strategy_log, dtype=[('date', 'O'),
                                           ('account_value', 'f8'),
                                           ('money', 'f8'),
                                           ('portfolio_value', 'f8'),
                                           ('loan_ratio', 'f8'),
                                           ('reference_value', 'f8')])

    # create a plot showing the behavior of the strategy
    plot = LinkedPlot(window_title=str(strategy))
    plot.add_plot("Account value", title_above=False)
    plot.add_subplot(matrix, "account_value", "Account value")
    plot.add_subplot(matrix, "reference_value", str(reference))

    for date, text in action_markers:
        plot.add_marker(date,
                        "Account value",
                        "account_value",
                        "Account value",
                        text=text)

    plot.show()
Example #8
0
    args = parser.parse_args()

    # load the strategy class
    import strategy
    try:
        strategy_class = getattr(strategy, args.strategy)
    except AttributeError:
        print('Could not import ' + args.strategy + ' from strategy')
        print("Available strategies are:")

        # print all items from the strategy module that end with "Strategy"
        for attr in dir(strategy):
            if attr.endswith("Strategy"):
                print("   " + attr)
                sys.exit(1)

    # parse the from/to dates
    from_date = parse_date(args.from_date)
    to_date = parse_date(args.to_date)

    money = float(args.money)

    # create the strategy instance
    strategy = strategy_class(money, [], from_date, to_date)

    # get the reference instument
    reference = get_instrument(args.reference.upper())

    # run the simulation
    simulate(strategy, money, from_date, to_date, reference)