예제 #1
0
def test_marketsim(description, group, inputs, outputs, grader):
    """Test compute_portvals() returns correct daily portfolio values.

    Requires test description, test case group, inputs, expected outputs, and a grader fixture.
    """

    points_earned = 0.0  # initialize points for this test case
    try:
        # Try to import student code (only once)
        if not main_code in globals():
            import importlib
            # * Import module
            mod = importlib.import_module(main_code)
            globals()[main_code] = mod
            # * Import methods to test
            for m in ['compute_portvals']:
                globals()[m] = getattr(mod, m)

        incorrect = False
        msgs = []

        if group == 'author':
            try:
                auth_string = run_with_timeout(marketsim.author,
                                               seconds_per_test_case, (), {})
                if auth_string == 'tb34':
                    incorrect = True
                    msgs.append("   Incorrect author name (tb34)")
                    points_earned = -10
                elif auth_string == '':
                    incorrect = True
                    msgs.append("   Empty author name")
                    points_earned = -10
            except Exception as e:
                incorrect = True
                msgs.append(
                    "   Exception occured when calling author() method: {}".
                    format(e))
                points_earned = -10
        else:
            # Unpack test case
            orders_file = inputs['orders_file']
            start_val = inputs['start_val']
            impct = inputs['impact']
            commish = inputs['commission']

            portvals = None
            fullpath_orders_file = get_orders_data_file(orders_file)
            portvals = run_with_timeout(
                compute_portvals, seconds_per_test_case, (), {
                    'orders_file': fullpath_orders_file,
                    'start_val': start_val,
                    'commission': commish,
                    'impact': impct
                })

            # * Check return type is correct, coax into Series
            assert (type(portvals) == pd.Series) or (
                type(portvals) == pd.DataFrame and len(portvals.columns)
                == 1), "You must return a Series or single-column DataFrame!"
            if type(portvals) == pd.DataFrame:
                portvals = portvals[portvals.columns[
                    0]]  # convert single-column DataFrame to Series
            if group == 'basic':
                if len(portvals) != outputs['num_days']:
                    incorrect = True
                    msgs.append(
                        "   Incorrect number of days: {}, expected {}".format(
                            len(portvals), outputs['num_days']))
                else:
                    points_earned += 2.0
                if abs(portvals[-1] - outputs['last_day_portval']) > (
                        0.001 * outputs['last_day_portval']):
                    incorrect = True
                    msgs.append(
                        "   Incorrect final value: {}, expected {}".format(
                            portvals[-1], outputs['last_day_portval']))
                else:
                    points_earned += 5.0
                adr, sr = get_stats(portvals)
                if abs(sr - outputs['sharpe_ratio']) > abs(
                        0.001 * outputs['sharpe_ratio']):
                    incorrect = True
                    msgs.append(
                        "   Incorrect sharpe ratio: {}, expected {}".format(
                            sr, outputs['sharpe_ratio']))
                else:
                    points_earned += 1.0
                if abs(adr - outputs['avg_daily_ret']) > abs(
                        0.001 * outputs['avg_daily_ret']):
                    incorrect = True
                    msgs.append(
                        "   Incorrect avg daily return: {}, expected {}".
                        format(adr, outputs['avg_daily_ret']))
                else:
                    points_earned += 1.0
            elif group == 'commission' or group == 'impact' or group == 'both':
                if abs(portvals[-1] - outputs['last_day_portval']) > 0.001:
                    incorrect = True
                    msgs.append(
                        "   Incorrect final value: {}, expected {}".format(
                            portvals[-1], outputs['last_day_portval']))
                else:
                    points_earned += 2.0
        if incorrect:
            raise IncorrectOutput, "Test failed on one or more output criteria.\n  Inputs:\n{}\n  Failures:\n{}".format(
                inputs, "\n".join(msgs))
    except Exception as e:
        # Test result: failed
        msg = "Test case description: {}\n".format(description)

        # Generate a filtered stacktrace, only showing erroneous lines in student file(s)

        tb_list = tb.extract_tb(sys.exc_info()[2])
        if 'grading_traceback' in dir(e):
            tb_list = e.grading_traceback
        for i in xrange(len(tb_list)):
            row = tb_list[i]
            tb_list[i] = (os.path.basename(row[0]), row[1], row[2], row[3]
                          )  # show only filename instead of long absolute path
        tb_list = [row for row in tb_list if row[0] == 'marketsim_old.py']
        if tb_list:
            msg += "Traceback:\n"
            msg += ''.join(tb.format_list(tb_list))  # contains newlines
        msg += "{}: {}".format(e.__class__.__name__, e.message)

        # Report failure result to grader, with stacktrace
        grader.add_result(
            GradeResult(outcome='failed',
                        points=max(points_earned, 0),
                        msg=msg))
        raise
    else:
        # Test result: passed (no exceptions)
        grader.add_result(
            GradeResult(outcome='passed', points=points_earned, msg=None))
예제 #2
0
def compute_portvals(orders_file="./orders/orders.csv", start_val=1000000):

    orders = get_orders_data_file(orders_file)
    orders_data = pd.read_csv(orders)
    orders_data.sort_values(by='Date', inplace=True, ascending=True)

    start_date = orders_data.iloc[0, 0]
    end_date = orders_data.iloc[len(orders_data) - 1, 0]

    adj_close_prices = get_data(['SPY'], pd.date_range(start_date, end_date))
    orders_data_new = orders_data.set_index('Date', inplace=False)
    orders_join = orders_data_new.join(adj_close_prices)

    adj_close_prices = adj_close_prices.join(orders_data_new)
    adj_close_prices = adj_close_prices[['SPY']]
    adj_close_prices.rename(columns={'SPY': 'Portval'}, inplace=True)
    portvals = pd.DataFrame().reindex_like(adj_close_prices)
    cash = start_val
    equity = 0
    portval = cash + equity
    shares_allocation = {}

    daily_cash = pd.DataFrame().reindex_like(adj_close_prices)
    daily_shares_allocation = {}

    df = adj_close_prices.index
    df1 = orders_join.index
    i = 0
    orders_data_index = 0

    value = df[0]

    while value in df:

        value1 = pd.to_datetime(value).strftime('%Y-%m-%d')
        if (value in df1):

            sd = orders_data.iloc[orders_data_index, 0]
            sym = orders_data.iloc[orders_data_index, 1]
            order = orders_data.iloc[orders_data_index, 2]
            shares = orders_data.iloc[orders_data_index, 3]

            adj_close_price = get_data([sym], pd.date_range(sd, sd))
            adj_close_price = adj_close_price[[sym]]

            commission = 9.95
            if (not np.isnan(adj_close_price.iloc[0, 0])):
                if (order == 'SELL'):
                    if (i != 0):
                        cash = daily_cash.iloc[i - 1, 0]
                    cash += adj_close_price.iloc[0, 0] * 0.995 * shares
                    cash -= commission

                    if (i != 0):
                        previous_date = pd.to_datetime(
                            df[i - 1]).strftime('%Y-%m-%d')
                        shares_allocation = daily_shares_allocation[
                            previous_date]
                    shares_allocation_n = shares_allocation.copy()
                    if (shares_allocation_n.has_key(sym)):
                        shares_allocation_n[sym] -= shares
                    else:
                        shares_allocation_n[sym] = 0 - shares

                if (order == 'BUY'):
                    if (i != 0):
                        cash = daily_cash.iloc[i - 1, 0]
                    cash -= adj_close_price.iloc[0, 0] * 1.005 * shares
                    cash -= commission

                    if (i != 0):
                        previous_date = pd.to_datetime(
                            df[i - 1]).strftime('%Y-%m-%d')
                        shares_allocation = daily_shares_allocation[
                            previous_date]
                    shares_allocation_n = shares_allocation.copy()
                    if (not shares_allocation.has_key(sym)):
                        shares_allocation_n[sym] = shares
                    else:
                        shares_allocation_n[sym] += shares

            orders_data_index += 1

            leverage = sum_of_abs_of_stock_positions(
                shares_allocation_n,
                value1) / (compute_equity(shares_allocation_n, value1) + cash)
            if (leverage <= 2.0):

                daily_shares_allocation[value1] = shares_allocation_n
                daily_cash.set_value(value1, 'Portval', cash)
                equity = compute_equity(shares_allocation_n, value1)
                portval = cash + equity
                portvals.set_value(sd, 'Portval', portval)

            else:
                last_date = pd.to_datetime(df[i - 1]).strftime('%Y-%m-%d')
                sa = daily_shares_allocation[last_date]
                daily_shares_allocation[value1] = sa
                c = daily_cash.iloc[i - 1, 0]
                daily_cash.set_value(value1, 'Portval', c)
                e = compute_equity(sa, value1)
                p = c + e
                portvals.set_value(sd, 'Portval', p)

            i += 1

            if (i == len(df)):
                break

            value = df[i]

        else:
            current_date = value1

            previous_date = pd.to_datetime(df[i - 1]).strftime('%Y-%m-%d')

            next_order_date = pd.to_datetime(
                df1[orders_data_index]).strftime('%Y-%m-%d')

            new_data = get_data(['SPY'],
                                pd.date_range(current_date, next_order_date))

            l = i + len(new_data) - 2
            b = i
            date_before_next_order_date = pd.to_datetime(
                df[l]).strftime('%Y-%m-%d')
            cash_new = daily_cash.iloc[i - 1, 0]
            shares_allocation_new = daily_shares_allocation[previous_date]

            equity = compute_equity_range(shares_allocation_new, current_date,
                                          date_before_next_order_date)
            portvals_intermed = equity + cash_new
            portvals['Portval'][
                current_date:date_before_next_order_date] = portvals_intermed
            daily_cash['Portval'][
                current_date:date_before_next_order_date] = cash_new

            for a in range(b, l + 1):
                date_assigned = pd.to_datetime(df[a]).strftime('%Y-%m-%d')
                daily_shares_allocation[date_assigned] = shares_allocation_new

            i = l + 1
            value = df[i]

    portvals = portvals.groupby(portvals.index).last()

    return portvals