コード例 #1
0
def optimization(weight_scheme):
    numberofday = 0
    quarter_list = []

    # Initialize matrix full of zeros
    resultMatrix = [[0 for x in range(len(ticker) + 5)]
                    for y in range(len(timestamp) + 1)]

    # Change the first row of result matrix to show headers
    firstrow = resultMatrix[0]
    secondrow = resultMatrix[1]
    for i0 in range(len(firstrow)):
        if i0 == 0:
            firstrow[i0] = ""
        elif i0 < len(ticker) + 1:
            firstrow[i0] = ticker[i0 - 1]
        elif i0 == len(ticker) + 1:
            firstrow[i0] = "Daily Return"
        elif i0 == len(ticker) + 2:
            firstrow[i0] = "Cumulative"
        elif i0 == len(ticker) + 3:
            firstrow[i0] = "Stock Count"
        elif i0 == len(ticker) + 4:
            firstrow[i0] = "Portfolio"
            secondrow[i0] = initial_amount

    # Change the first column of result matrix to show time index
    for row in range(len(resultMatrix)):
        if row == 0:
            resultMatrix[row][0] = ""
        else:
            resultMatrix[row][0] = timestamp[row - 1]

    resultMatrix = np.array(resultMatrix)
    column_return = np.array(resultMatrix[:, -1][1:])  # Portfolio
    column_return = np.asfarray(column_return, float)
    column_return[0] = initial_amount

    # Loop through time index
    cash_amount = 0
    for index in range(len(timestamp)):
        bool_quarter = False
        stockcount = 0
        answer = 0  # search for index for weights
        month = int(timestamp[index].split("/")[1])
        year = int(timestamp[index].split("/")[2])
        if month < 7:
            quarter = "Q2"
        else:
            quarter = "Q4"
        current = str(year) + quarter

        # Q-2 quarter
        if month < 4:
            year -= 1
            quarter = "Q2"
        elif month < 7:
            year -= 1
            quarter = "Q4"
        elif month < 10:
            year -= 1
            quarter = "Q4"
        else:
            quarter = "Q2"
        date = str(year) + quarter

        # Check if quarter is different from previous day's quarter
        quarter_list.append(current)
        if index == 0:
            store_index.append([index, current])
        else:
            if quarter_list[index] != quarter_list[index - 1]:
                store_index.append([index, current])
        if (index
                == 0) or (index != 0
                          and quarter_list[index] != quarter_list[index - 1]):
            bool_quarter = True

        # Search for index for weights
        for index2 in range(len(weight_scheme)):
            if date == weight_scheme[index2][0]:
                answer = index2

        # Loop through stocks
        aggregate = 0
        cash_hand = 100
        for stock in range(len(ticker)):
            gain = functions.percentageChange(
                float(price[index - 1][stock + 1]),
                float(price[index][stock + 1]))
            if answer == 0:
                stockweight = 0
            else:
                w = float(weight_scheme[answer][stock + 1])
                stockweight = w / 100
            if bool_quarter:  # When quarter changes
                if index == 0:
                    value = initial_amount * stockweight
                else:
                    value = column_return[index - 1] * stockweight
                    cash_hand -= w
            else:  # When quarter does not change
                value = float(
                    resultMatrix[index][stock + 1]) * (1 + gain / 100)
            resultMatrix[index + 1][
                stock +
                1] = value  # Fill in the money allocation instead of percentage change
            aggregate += value
            # Calculate number of stocks to be invested
            if stockweight != 0 and float(price[index][stock + 1]) != 0:
                stockcount += 1
        # Calculate cash in hand when remaining weight is not zero
        if bool_quarter and cash_hand < 100:
            cash_amount = cash_hand * column_return[index - 1] / 100
        if bool_quarter and cash_hand == 100:
            cash_amount = 0
        if aggregate == 0:
            aggregate = column_return[index - 1]
            if column_return[index - 1] == 0 or index == 0:
                aggregate = initial_amount
        aggregate += cash_amount
        column_return[index] = aggregate

        # Stock Count
        resultMatrix[index + 1][len(ticker) + 3] = stockcount
        numberofday += 1

    resultMatrix[:, -1][1:] = column_return
    daily_return = functions.percentagelist(column_return)
    resultMatrix[:, -4][2:] = daily_return
    cumulative = functions.cumulative_list(daily_return)
    resultMatrix[:, -3][2:] = cumulative
    portfolio_list = column_return

    # Take the last index to get cumulative_return
    cumulative_return = cumulative[-1]  # Final cumulative return
    list_cumulative.append(cumulative_return)
    # Calculate related stats
    sharpe_ratio = sharpe(daily_return)
    list_sharpe.append(sharpe_ratio)
    print(numberofday, "days;", round(cumulative_return, 4), "%, Sharpe = ",
          round(sharpe_ratio, 4))

    return column_return
コード例 #2
0
def trend_following(weight_scheme, number):
    quarter_list = []
    # Weight Scheme 1: Third Last Column
    # Weight Scheme 2: Second Last Column
    # Weight Optimized: Last Column
    column_return = np.array(result_matrix[:, number - 4][1:])
    column_return = np.asfarray(column_return, float)
    column_return[0] = initial_amount

    # Loop through time index
    cash_amount = 0
    for index in range(len(timestamp)):
        bool_quarter = False
        answer = 0  # search for index for weights
        month = int(timestamp[index].split("/")[1])
        year = int(timestamp[index].split("/")[2])
        if month < 7:
            quarter = "Q2"
        else:
            quarter = "Q4"
        current = str(year) + quarter

        # Q-2 quarter
        if month < 4:
            year -= 1
            quarter = "Q2"
        elif month < 7:
            year -= 1
            quarter = "Q4"
        elif month < 10:
            year -= 1
            quarter = "Q4"
        else:
            quarter = "Q2"
        date = str(year) + quarter

        # Check if quarter is different from previous day's quarter
        quarter_list.append(current)
        if number == 1:
            if index == 0:
                store_index.append([index, current])
            else:
                if quarter_list[index] != quarter_list[index - 1]:
                    store_index.append([index, current])
        if (index
                == 0) or (index != 0
                          and quarter_list[index] != quarter_list[index - 1]):
            bool_quarter = True

        # Search for index for weights
        for index2 in range(len(weight_scheme)):
            if date == weight_scheme[index2][0]:
                answer = index2

        # Loop through stocks
        aggregate = 0
        cash_hand = 100
        if number == 1:
            w_return = w1_matrix
        elif number == 2:
            w_return = w2_matrix
        else:
            w_return = w3_matrix
        for stock in range(len(tickers)):
            # Import results after market timing
            gain = float(w_return[index + 1][stock + 1])
            if answer == 0:
                stockweight = 0
            else:
                w = float(weight_scheme[answer][stock + 1])
                stockweight = w / 100
            if bool_quarter:  # When quarter changes, change the initial amount and re-balance
                if index == 0:
                    value = initial_amount * stockweight
                else:
                    value = column_return[index - 1] * stockweight
                    cash_hand -= w
            else:  # When quarter doesn't change
                value = float(
                    result_matrix1[index][stock + 1]) * (1 + gain / 100)
            result_matrix1[index + 1][
                stock +
                1] = value  # Fill in the money allocation instead of percentage change
            aggregate += value
        # Calculate cash in hand when remaining weight is not zero
        if bool_quarter and cash_hand < 100:
            cash_amount = cash_hand * column_return[index - 1] / 100
        if bool_quarter and cash_hand == 100:
            cash_amount = 0
        if aggregate == 0:
            aggregate = column_return[index - 1]
            if column_return[index - 1] == 0 or index == 0:
                aggregate = initial_amount
        aggregate += cash_amount
        column_return[index] = aggregate

    result_matrix1[:, -2][1:] = column_return  # Portfolio
    list_return = functions.percentagelist(column_return)
    result_matrix1[:, -1][2:] = list_return  # Daily Return
    cumulative = functions.cumulative_list(list_return)
    result_matrix[:, number - 4][2:] = cumulative  # Market Timing Strategy.csv

    if number == 1:
        # Write csv file of result matrix inside result folder
        with open(directory + 'Combined Strategy 1.csv', "w") as output:
            writer = csv.writer(output, lineterminator='\n')
            for val in result_matrix1:
                writer.writerow(val)
    elif number == 2:
        # Write csv file of result matrix inside result folder
        with open(directory + 'Combined Strategy 2.csv', "w") as output:
            writer = csv.writer(output, lineterminator='\n')
            for val in result_matrix1:
                writer.writerow(val)
    else:
        # Write csv file of result matrix inside result folder
        with open(directory + 'Combined Strategy Optimized Weight.csv',
                  "w") as output:
            writer = csv.writer(output, lineterminator='\n')
            for val in result_matrix1:
                writer.writerow(val)
コード例 #3
0
def backtest(weight_scheme, number):
    numberofday = 0
    quarter_list = []

    # Initialize matrix full of zeros
    resultMatrix = [[0 for x in range(len(ticker) + 5)]
                    for y in range(len(timestamp) + 1)]

    # Change the first row of result matrix to show headers
    firstrow = resultMatrix[0]
    secondrow = resultMatrix[1]
    for i0 in range(len(firstrow)):
        if i0 == 0:
            firstrow[i0] = ""
        elif i0 < len(ticker) + 1:
            firstrow[i0] = ticker[i0 - 1]
        elif i0 == len(ticker) + 1:
            firstrow[i0] = "Daily Return"
        elif i0 == len(ticker) + 2:
            firstrow[i0] = "Cumulative"
        elif i0 == len(ticker) + 3:
            firstrow[i0] = "Stock Count"
        elif i0 == len(ticker) + 4:
            firstrow[i0] = "Portfolio"
            secondrow[i0] = initial_amount

    # Change the first column of result matrix to show time index
    for row in range(len(resultMatrix)):
        if row == 0:
            resultMatrix[row][0] = ""
        else:
            resultMatrix[row][0] = timestamp[row - 1]

    resultMatrix = np.array(resultMatrix)
    column_return = np.array(resultMatrix[:, -1][1:])  # Portfolio
    column_return = np.asfarray(column_return, float)
    column_return[0] = initial_amount

    # Loop through time index
    for index in range(len(timestamp)):
        bool_quarter = False
        stockcount = 0
        answer = 0  # search for index for weights
        month = int(timestamp[index].split("/")[1])
        year = int(timestamp[index].split("/")[2])
        if month < 7:
            quarter = "Q2"
        else:
            quarter = "Q4"
        current = str(year) + quarter

        # Q-2 quarter
        if month < 4:
            year -= 1
            quarter = "Q2"
        elif month < 7:
            year -= 1
            quarter = "Q4"
        elif month < 10:
            year -= 1
            quarter = "Q4"
        else:
            quarter = "Q2"
        date = str(year) + quarter

        # Check if quarter is different from previous day's quarter
        quarter_list.append(current)
        if number == 1:
            if index == 0:
                store_index.append([index, current])
            else:
                if quarter_list[index] != quarter_list[index - 1]:
                    store_index.append([index, current])
        if (index
                == 0) or (index != 0
                          and quarter_list[index] != quarter_list[index - 1]):
            bool_quarter = True

        # Search for index for weights
        for index2 in range(len(weight_scheme)):
            if date == weight_scheme[index2][0]:
                answer = index2

        # Loop through stocks
        aggregate = 0
        for stock in range(len(ticker)):
            gain = functions.percentageChange(
                float(price[index - 1][stock + 1]),
                float(price[index][stock + 1]))
            if answer == 0:
                stockweight = 0
            else:
                stockweight = float(weight_scheme[answer][stock + 1]) / 100
            if bool_quarter:  # When quarter changes
                if index == 0:
                    value = initial_amount * stockweight
                else:
                    value = column_return[index - 1] * stockweight
            else:  # When quarter does not change
                value = float(
                    resultMatrix[index][stock + 1]) * (1 + gain / 100)
            resultMatrix[index + 1][
                stock +
                1] = value  # Fill in the money allocation instead of percentage change
            aggregate += value
            # Calculate number of stocks to be invested
            if stockweight != 0 and float(price[index][stock + 1]) != 0:
                stockcount += 1
        if aggregate == 0:
            aggregate = column_return[index - 1]
            if column_return[index - 1] == 0 or index == 0:
                aggregate = initial_amount
        column_return[index] = aggregate

        # Stock Count
        resultMatrix[index + 1][len(ticker) + 3] = stockcount
        numberofday += 1

    resultMatrix[:, -1][1:] = column_return
    daily_return = functions.percentagelist(column_return)
    resultMatrix[:, -4][2:] = daily_return
    cumulative = functions.cumulative_list(daily_return)
    resultMatrix[:, -3][2:] = cumulative
    portfolio_list = column_return

    # Take the last index to get cumulative_return
    cumulative_return = cumulative[-1]  # Final cumulative return

    # Calculate related stats
    head = "Weight Scheme " + str(number)
    print(head, ":")
    print(numberofday, "days;", round(cumulative_return, 4), "%")
    print("\n")
    print("Average Daily Return =", round(average(daily_return), 4), "%")
    print("SD of Daily Return =", round(SD(daily_return), 4), "%")
    annual_return = average(daily_return) * oneyear
    print("Annualized Return =", round(annual_return, 4), "%")
    annual_volatility = SD(daily_return) * (oneyear**(1 / 2))
    print("Annualized Volatility =", round(annual_volatility, 4), "%")
    sharpe_ratio = sharpe(daily_return)
    print("Annual Sharpe Ratio: ", round(sharpe_ratio, 4))
    print("Max Consecutive Loss = ", maxconsecutive(daily_return), "days")
    print("Win Rate:", round(winrate(daily_return), 4), "%")
    max_drawdown = functions.findMin(daily_return)
    print("Max Drawdown:", round(max_drawdown, 4), "%")
    print("\n")
    stats_line = [
        head, cumulative_return, annual_return, annual_volatility,
        sharpe_ratio, max_drawdown
    ]
    stats_matrix.append(stats_line)

    if number == 2:
        # Calculate stats for market index
        daily_return_index = functions.percentagelist(price_index)
        cumulative_index = functions.percentageChange(price_index[0],
                                                      price_index[-1])
        print(market, "Index: ")
        print("Cumulative =", round(cumulative_index, 4), "%")
        print("Average Daily Return =", round(average(daily_return_index), 4),
              "%")
        print("SD of Daily Return =", round(SD(daily_return_index), 4), "%")
        annual_return = average(daily_return_index) * oneyear
        print("Annualized Return =", round(annual_return, 4), "%")
        annual_volatility = SD(daily_return_index) * (oneyear**(1 / 2))
        print("Annualized Volatility =", round(annual_volatility, 4), "%")
        sharpe_ratio = sharpe(daily_return_index)
        print("Annual Sharpe Ratio: ", round(sharpe_ratio, 4))
        print("Max Consecutive Loss = ", maxconsecutive(daily_return_index),
              "days")
        print("Win Rate:", round(winrate(daily_return_index), 4), "%")
        max_drawdown = functions.findMin(daily_return)
        print("Max Drawdown:", round(max_drawdown, 4), "%")
        stats_line = [
            market, cumulative_index, annual_return, annual_volatility,
            sharpe_ratio, max_drawdown
        ]
        stats_matrix.append(stats_line)

    # Find correct date to match dates for market index and our portfolio
    correctdate = []
    correctdate2 = []
    for i in range(len(timestamp)):
        for j in range(len(date_index)):
            if date_index[j] == timestamp[i]:
                correctdate.append(i)
                correctdate2.append(j)

    # Prepare for a graph
    x_axis = date_index
    y = []  # Strategy Portfolio
    y_index = []  # Market Index Portfolio

    # Normalize to initial amount and fill up values for y-axis by searching for correct dates
    relative_portfolio = functions.relative(portfolio_list)
    for i in range(len(correctdate)):
        correctindex = correctdate[i] - 1
        y.append(relative_portfolio[correctindex])
    for j in range(len(correctdate2)):
        correctindex = correctdate2[j]
        y_index.append(price_index[correctindex])
    y_index = functions.relative(y_index)

    # Plot a graph
    fig = plt.figure()  # Create a figure
    ax = plt.axes()  # Create axis
    if len(x_axis) == len(y):
        plt.plot(x_axis, y, label='Weight Scheme ' + str(number))
        plt.plot(x_axis, y_index, label=market)
        ax.xaxis.set_major_locator(
            plt.MaxNLocator(5))  # Set Maximum number of x-axis values to show
        fig.autofmt_xdate()  # Rotate values to see more clearly
        title = "Stock Selection: Growth of " + str(
            initial_amount / 1000000) + " million"
        plt.title(title)
        plt.ylabel("Cumulative Return")
        fig.savefig(directory + market + " Stock Selection Weight Scheme " +
                    str(number) + ".png")
        plt.show()

    # Write csv file of result matrix inside result folder
    title = directory + 'weight scheme ' + str(number)
    with open(title + ' result.csv', "w") as output:
        writer = csv.writer(output, lineterminator='\n')
        for val in resultMatrix:
            writer.writerow(val)
コード例 #4
0
    y.append(portfolio_pure[correctindex])
    strategy1.append(portfolio_weight1[correctindex])
    strategy2.append(portfolio_weight2[correctindex])
    strategy3.append(portfolio_weight_optimized[correctindex])
for j in range(len(correctdate2)):
    correctindex = correctdate2[j]
    y_index.append(price_index[correctindex])
    x_axis.append(date_index[correctindex])

title_stats = [
    "Pure Market Trending", "Weight Scheme 1", "Weight Scheme 2",
    'Weight Optimized', market
]
stats = [y, strategy1, strategy2, strategy3, y_index]
for count in range(len(stats)):
    calculate = functions.percentagelist(stats[count])
    cumulative_return = functions.percentageChange(stats[count][0],
                                                   stats[count][-1])
    annualized_return = average(calculate) * 252
    annuzlied_volatility = SD(calculate) * (252**(1 / 2))
    sharpe_ratio = sharpe(calculate)
    max_drawdown = functions.findMin(calculate)
    print(title_stats[count])
    print("Cumulative Return:", round(cumulative_return, 4), "%")
    print("Annualized Return:", round(annualized_return, 4), "%")
    print("Annualized Volatility:", round(annuzlied_volatility, 4), "%")
    print("Sharpe Ratio:", round(sharpe_ratio, 4))
    print("Max Drawdown:", round(max_drawdown, 4), "%")
    print("\n")
    stats_line = [
        title_stats[count], cumulative_return, annualized_return,
コード例 #5
0
# Calculate related stats
print(numberofday, "days;", round(cumulative_return, 4), "%")
print("\n")
print("Average Daily Return =", round(average(daily_return), 4), "%")
print("SD of Daily Return =", round(SD(daily_return), 4), "%")
print("Annualized Return =", round(average(daily_return) * oneyear, 4), "%")
print("Annualized Volatility =",
      round(SD(daily_return) * (oneyear**(1 / 2)), 4), "%")
print("Annual Sharpe Ratio: ", round(sharpe(daily_return), 4))
print("Max Consecutive Loss = ", maxconsecutive(daily_return), "days")
print("Win Rate:", round(winrate(daily_return), 4), "%")
print("Max Drawdown:", round(functions.findMin(daily_return), 4), "%")
print("\n")

# Calculate stats for market index
daily_return_index = functions.percentagelist(price_index)
cumulative_index = functions.percentageChange(price_index[0], price_index[-1])
print(market, "Index: ")
print("Cumulative =", round(cumulative_index, 4), "%")
print("Average Daily Return =", round(average(daily_return_index), 4), "%")
print("SD of Daily Return =", round(SD(daily_return_index), 4), "%")
print("Annualized Return =", round(average(daily_return_index) * oneyear, 4),
      "%")
print("Annualized Volatility =",
      round(SD(daily_return_index) * (oneyear**(1 / 2)), 4), "%")
print("Annual Sharpe Ratio: ", round(sharpe(daily_return_index), 4))
print("Max Consecutive Loss = ", maxconsecutive(daily_return_index), "days")
print("Win Rate:", round(winrate(daily_return_index), 4), "%")
print("Max Drawdown:", round(functions.findMin(daily_return_index), 4), "%")

# Find correct date to match dates for market index and our portfolio