Exemplo n.º 1
0
    def test_generate_factor(self):
        test_factor_returns = [ [0.01, 0.02, 0.03], \
              [0.02, -0.05, 0.08], \
              [0.07, 0.05, 0.03], \
              [0.02, 0.01, -0.09]]
        # Three factors' history in 4-day period

        test_asset_returns = [ [0.04, 0.06], \
              [0.03, -0.02], \
              [0.01, 0.04], \
              [0.04, 0.02]]

        expected_returns = [0.0302, 0.0242]

        test_expected_returns, test_covariance_matrix = factor_model.generate_factor(
            test_factor_returns, test_asset_returns)

        for i in range(len(test_expected_returns)):
            self.assertEqual(expected_returns[i],
                             round(test_expected_returns[i], 4))

        expected_covariance_matrix = [[0.0002, 0.0], [0.0, 0.0012]]
        for i in range(len(expected_covariance_matrix)):
            for j in range(len(expected_covariance_matrix[0])):
                self.assertEqual(expected_covariance_matrix[i][j],
                                 round(test_covariance_matrix[i][j], 4))
def port_cont_procedure(asset_data, user_input, id_ticker_mapping,
                        ticker_id_mapping, factor_data):
    '''
		Start and end date in user_input is for user to select what range of data to look at
		If the user doesn't specify these two dates, default date will be used
		The end date for look back is "2018-09-30" for factor data availability
	'''
    if "investment_length" not in user_input or user_input[
            "investment_length"] > MAX_LOOK_BACK_L:
        user_input["investment_length"] = LOOK_BACK_L
    if "target_return" not in user_input: user_input["target_return"] = 0.1
    user_input["end_date"] = "2018-09-30"
    feasible_end_date_index = find_next_available_date_index(
        asset_data, user_input["end_date"], "SP500", -1)
    dates = asset_data["SP500"]["dates"]\
      [feasible_end_date_index - user_input["investment_length"]: feasible_end_date_index + 1]
    factor_matrix = prepare_factor_matrix(factor_data, 0,
                                          len(dates) - 1, dates)
    assets_included, asset_return_matrix = prepare_asset_return_matrix(asset_data, \
               dates[0], dates[-1], dates)
    expected_returns, covariance_matrix = factor_model.generate_factor(
        factor_matrix, asset_return_matrix)
    mvo_weight = MVO.get_weight_from_MVO(expected_returns, covariance_matrix, \
              user_input["target_return"])
    mvo_port = {"weight": {}, "start_date": dates[0], "end_date": "2018-10-31"}
    for i in range(len(assets_included)):
        if assets_included[i] in id_ticker_mapping:
            mvo_port["weight"][id_ticker_mapping[
                assets_included[i]]] = mvo_weight[i]
        else:
            mvo_port["weight"][assets_included[i]] = mvo_weight[i]
    mvo_port_back_test_res = back_testing_procedure(asset_data, mvo_port, \
                 id_ticker_mapping, ticker_id_mapping, False)
    cur_price = []
    for i in range(len(assets_included)):
        try:
            cur_price.append(asset_data[assets_included[i]]["price_his"]\
                 [asset_data[assets_included[i]]["dates"].index(dates[0])])
        except:
            import pdb
            pdb.set_trace()
    cvar_weight = cvar.get_optimal_weight_by_CVaR(expected_returns, covariance_matrix, cur_price, \
            10, int(user_input["investment_length"]), \
            int(user_input["investment_length"] / 4) )
    cvar_port = {
        "weight": {},
        "start_date": dates[0],
        "end_date": "2018-10-31"
    }
    for i in range(len(assets_included)):
        if assets_included[i] in id_ticker_mapping:
            cvar_port["weight"][id_ticker_mapping[
                assets_included[i]]] = cvar_weight[i]
        else:
            cvar_port["weight"][assets_included[i]] = cvar_weight[i]
    cvar_port_back_test_res = back_testing_procedure(asset_data, cvar_port, \
                 id_ticker_mapping, ticker_id_mapping, False)
    # import pdb; pdb.set_trace()
    if not os.path.exists("img"):
        os.mkdir("img")
    plot_and_save(dates + ["2018-10-31"], [cvar_port_back_test_res["portfolio_values"], \
              mvo_port_back_test_res["portfolio_values"]], \
         ["CVaR", "MVO"], "img/port_c_res.png")
    if cvar_port_back_test_res["stats"]["sharpe"] > mvo_port_back_test_res[
            "stats"]["sharpe"]:
        return {
            "port": cvar_port,
            "back_test": cvar_port_back_test_res,
            "taken": "CVaR",
            "objective": "c"
        }
    else:
        return {
            "port": mvo_port,
            "back_test": mvo_port_back_test_res,
            "taken": "MVO",
            "objective": "c"
        }
def port_domi_procedure(asset_data, user_input, id_ticker_mapping,
                        ticker_id_mapping, factor_data):
    original_user_input = copy.deepcopy(user_input)
    if user_input["start_date"] < "2004-01-31":
        user_input["start_date"] = "2004-01-31"
    if user_input["end_date"] > "2018-10-31":
        user_input["end_date"] = "2018-10-31"
    user_port_res_whole = back_testing_procedure(asset_data, user_input,
                                                 id_ticker_mapping,
                                                 ticker_id_mapping, False)
    feasible_start_date_index = find_next_available_date_index(
        asset_data, user_input["start_date"], "SP500", +1)
    feasible_end_date_index = find_next_available_date_index(
        asset_data, user_input["end_date"], "SP500", -1)
    dates = asset_data["SP500"]["dates"][
        feasible_start_date_index:feasible_end_date_index + 1]
    dates = asset_data["SP500"][
        "dates"][feasible_start_date_index -
                 LOOK_BACK_L:feasible_start_date_index] + dates
    portfolio_values = [INITIAL_PORFOLIO_VALUE]
    cur_portfolio = {}
    cur_returns = []
    start_debug = False
    for i in range(LOOK_BACK_L, len(dates), 1):
        date = dates[i]
        user_input["start_date"] = dates[
            i - LOOK_BACK_L]  # Look back 4 years each time
        user_input["end_date"] = date
        user_port_res = back_testing_procedure(asset_data, user_input,
                                               id_ticker_mapping,
                                               ticker_id_mapping, False)
        factor_matrix = prepare_factor_matrix(factor_data, i - LOOK_BACK_L, i,
                                              dates)
        assets_included, asset_return_matrix = prepare_asset_return_matrix(asset_data, \
                  user_input["start_date"], user_input["end_date"], dates)
        expected_returns, covariance_matrix = factor_model.generate_factor(
            factor_matrix, asset_return_matrix)
        weight = MVO.get_weight_from_MVO(expected_returns, covariance_matrix, \
                 user_port_res["stats"]["mean_return"] * AMPLIFY_FACTOR)
        new_port_value = 0
        for asset_name in cur_portfolio.keys():
            if date in asset_data[asset_name]["dates"]:
                new_port_value += asset_data[asset_name]["price_his"][asset_data[asset_name]["dates"].index(date)] \
                    * cur_shares[asset_name]
            else:
                new_port_value += portfolio_values[-1] * cur_portfolio[
                    asset_name]
        if new_port_value != 0:
            portfolio_values.append(new_port_value)
        cur_portfolio = {}  # {asset_name: weight(decimal)}
        for ticker in user_input["weight"]:
            asset_name = ticker_id_mapping[ticker]
            cur_portfolio[
                asset_name] = user_input["weight"][ticker] * ORIGINAL_CONSTANT
        for j2 in range(len(weight)):
            if assets_included[j2] in cur_portfolio:
                cur_portfolio[assets_included[j2]] += weight[j2] * (
                    1 - ORIGINAL_CONSTANT)
            else:
                cur_portfolio[
                    assets_included[j2]] = weight[j2] * (1 - ORIGINAL_CONSTANT)
        cur_shares = {}  # {asset_name: #shares}
        for asset_name in cur_portfolio.keys():
            if date in asset_data[asset_name]["dates"]:
                cur_shares[asset_name] = portfolio_values[-1] * cur_portfolio[asset_name] / \
                   asset_data[asset_name]["price_his"][asset_data[asset_name]["dates"].index(date)]
        if len(portfolio_values) > 1:
            cur_returns.append(portfolio_values[-1] / portfolio_values[-2] - 1)
    stats = {}
    stats["total_return"] = portfolio_values[-1] / portfolio_values[0] - 1
    stats["mean_return"] = numpy.mean(cur_returns)
    stats["volitility"] = numpy.std(cur_returns) / (len(cur_returns)**0.5)
    stats["sharpe"] = stats["mean_return"] / stats["volitility"]
    if not os.path.exists("img"):
        os.mkdir("img")
    plot_and_save(user_port_res_whole["dates"], [user_port_res_whole["portfolio_values"], portfolio_values]\
        , ["user's portfolio", "improved portfolio"], "img/domi_res.png")
    return { "original_value": {"portfolio_values": user_port_res_whole["portfolio_values"], \
            "stats": user_port_res_whole["stats"]}, \
       "dominant": {"portfolio_values": portfolio_values, "stats": stats}, \
       "dates": user_port_res_whole["dates"], "objective": "d"}