def test_constant_weights_fully_invested(self): expected_series = self.rets_for_fully_invested_const_weights actual_series, _ = Portfolio.constant_weights(self.assets_df, self.weights_full_invest) assert_series_equal(expected_series, actual_series, absolute_tolerance=1e-06)
def test_log_returns_to_prices(self): prices_values = array([1, exp(1), exp(2), exp(-1), exp(2)]) prices_dates = pd.date_range('2015-01-01', periods=5) expected = PricesSeries(data=prices_values, index=prices_dates) returns_tms = LogReturnsSeries(data=[1, 1, -3, 3], index=expected.index[1::]) actual = returns_tms.to_prices() assert_series_equal(expected, actual)
def test_min_max_normalized(self): actual_normalized_tms = self.test_returns_tms.min_max_normalized() expected_normalized_values = array([3, 4, 5, 4, 3, 2, 1, 0, 3, 5, 7, 6, 5, 4, 3, 2, 3, 5, 4, 6]) / 7 expected_normalized_tms = SimpleReturnsSeries(data=expected_normalized_values, index=self.test_returns_tms.index) assert_series_equal(expected_normalized_tms, actual_normalized_tms)
def test_portfolio_eod_series(self): expected_portfolio_eod_series = PricesSeries() # Empty portfolio portfolio, dh, timer = self.get_portfolio_and_data_handler() portfolio.update(record=True) expected_portfolio_eod_series[timer.time] = self.initial_cash contract = self.fut_contract ticker = portfolio.contract_ticker_mapper.contract_to_ticker(contract) # Buy contract self._shift_timer_to_next_day(timer) transaction_1 = Transaction(timer.time, contract, quantity=50, price=250, commission=7) portfolio.transact_transaction(transaction_1) self.data_handler_prices = self.prices_series portfolio.update(record=True) position = portfolio.open_positions_dict[contract] price_1 = dh.get_last_available_price(ticker) pnl = contract.contract_size * transaction_1.quantity * (price_1 - transaction_1.price) nav = self.initial_cash + pnl - transaction_1.commission expected_portfolio_eod_series[timer.time] = nav # Contract goes up in value self._shift_timer_to_next_day(timer) self.data_handler_prices = self.prices_up portfolio.update(record=True) price_2 = dh.get_last_available_price(ticker) # == 270 pnl = contract.contract_size * transaction_1.quantity * (price_2 - price_1) nav += pnl expected_portfolio_eod_series[timer.time] = nav # Sell part of the contract self._shift_timer_to_next_day(timer) transaction_2 = Transaction(timer.time, contract, quantity=-25, price=price_2, commission=19) portfolio.transact_transaction(transaction_2) self.data_handler_prices = self.prices_up portfolio.update(record=True) pnl = (transaction_2.price - price_2) * transaction_2.quantity * contract.contract_size - transaction_2.commission nav += pnl expected_portfolio_eod_series[timer.time] = nav # Price goes down self._shift_timer_to_next_day(timer) self.data_handler_prices = self.prices_down portfolio.update(record=True) price_3 = dh.get_last_available_price(ticker) # == 210 pnl2 = contract.contract_size * position.quantity() * (price_3 - price_2) nav += pnl2 expected_portfolio_eod_series[timer.time] = nav tms = portfolio.portfolio_eod_series() assert_series_equal(expected_portfolio_eod_series, tms)
def test_import_series(self): template_file_path = self.template_file_path(SINGLE_SHEET_ONE_SERIES) imported_series = self.xl_importer.import_container( file_path=template_file_path, container_type=QFSeries, starting_cell='A1', ending_cell='B10') assert_series_equal(self.test_series, imported_series)
def test_rolling_volatility(self): dates = self.log_returns_tms.index[2::] values = [0.90138781886599728, 0.8832285053076373, 0.59074654587899456, 0.15030832509532852, 0.48257709858871728] expected_series = QFSeries(index=dates, data=values) actual_series = rolling_volatility(self.log_returns_tms, annualise=False, window_size=3) assert_series_equal(expected_series, actual_series)
def test_correct_behaviour_when_there_are_no_duplicates(self): no_duplicates_series = self.test_series.iloc[[0, 1, 3]] actual_series = drop_consecutive_duplicates(no_duplicates_series, Method.KEEP_FIRST) assert_series_equal(no_duplicates_series, actual_series) actual_series = drop_consecutive_duplicates(no_duplicates_series, Method.KEEP_LAST) assert_series_equal(no_duplicates_series, actual_series)
def test_get_factor_return_attribution(self): actual_regressors_return, actual_unexplained_return = ReturnAttributionAnalysis.get_factor_return_attribution( self.fund_returns_tms, self.fit_returns_tms, self.regressors_returns_df, self.coefficients, self.alpha ) expected_regressors_return = pd.Series(data=1.0e+61 * np.array([7.8183, 7.8578, 7.7788]), index=self.coefficients.index) expected_unexplained_return = -1.6784e+62 assert_series_equal(expected_regressors_return, actual_regressors_return, absolute_tolerance=1.0e57) self.assertAlmostEqual(expected_unexplained_return/1e+62, actual_unexplained_return/1e+62, delta=1e-05)
def test_drawdown_tms(self): test_prices = [100, 90, 80, 85, 70, 100, 90, 95, 65] prices_tms = PricesSeries(data=test_prices, index=date_range('2015-01-01', periods=9)) expected_drawdown_values = [0, 0.1, 0.2, 0.15, 0.3, 0, 0.1, 0.05, 0.35] expected_drawdowns_tms = QFSeries(expected_drawdown_values, date_range('2015-01-01', periods=9)) actual_drawdowns_tms = drawdown_tms(prices_tms) assert_series_equal(expected_drawdowns_tms, actual_drawdowns_tms)
def _assert_last_prices_are_correct(self, curr_time_str, expected_values, frequency): current_time = str_to_date(curr_time_str, DateFormat.FULL_ISO) self.current_time = current_time expected_series = QFSeries(data=expected_values, index=[self.ticker_1, self.ticker_2]) actual_series = self.data_provider.get_last_available_price( [self.ticker_1, self.ticker_2], frequency) assert_series_equal(expected_series, actual_series, check_names=False)
def test_price_multiple_tickers_single_field_order(self): data1 = self.bbg_provider.get_price(tickers=self.MANY_TICKERS, fields=self.SINGLE_PRICE_FIELD, start_date=self.START_DATE, end_date=self.END_DATE) data2 = self.bbg_provider.get_price(tickers=[self.MANY_TICKERS[1], self.MANY_TICKERS[0]], fields=self.SINGLE_PRICE_FIELD, start_date=self.START_DATE, end_date=self.END_DATE) assert_series_equal(data2.iloc[:, 0], data1.iloc[:, 1]) assert_series_equal(data2.iloc[:, 1], data1.iloc[:, 0])
def test_tail_events(self): expected_dates = DatetimeIndex(['2015-01-06', '2015-01-07', '2015-01-08', '2015-01-16'], freq=None) expected_benchmark_tail = SimpleReturnsSeries(index=expected_dates, data=[0, -0.01, -0.02, 0]) expected_examined_tail = SimpleReturnsSeries(index=expected_dates, data=[0.02, 0.01, 0.00, 0.02]) actual_benchmark_tail, actual_examined_tail = \ tail_events(self.test_simple_returns_tms, self.test_simple_returns_tms + 0.02, 25.0) assert_series_equal(expected_benchmark_tail, actual_benchmark_tail) assert_series_equal(expected_examined_tail, actual_examined_tail)
def test_stats_functions(self): qf_df = QFDataFrame(data=self.prices_values, index=self.dates, columns=self.column_names) max_qf_df = qf_df.max() expected_max = QFSeries([5, 5, 5, 5, 5], index=['a', 'b', 'c', 'd', 'e']) self.assertEqual(type(max_qf_df), QFSeries) assert_series_equal(max_qf_df, expected_max) self.assertEqual(dtype("float64"), max_qf_df.dtypes)
def test_get_volume_weighted_average_price(self): original_datetimes = date_range('2015-01-01', periods=12, freq='10Min') prices_tms = PricesSeries(data=[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4], index=original_datetimes) volumes_tms = QFSeries(data=[1, 2, 3, 4, 1, 2, 4, 3, 2, 1, 3, 4], index=original_datetimes) interval = Timedelta('40 min') expected_datetimes = date_range('2015-01-01 00:40', periods=2, freq=interval) expected_avg_weighted_prices = [3, 2.9] expected_prices_tms = PricesSeries(data=expected_avg_weighted_prices, index=expected_datetimes) actual_prices_tms = volume_weighted_average_price(prices_tms, volumes_tms, interval) assert_series_equal(expected_prices_tms, actual_prices_tms, absolute_tolerance=0.0)
def test_get_risk_contribution_optimised(self): weights = pd.Series([0.5, 0.5], index=self.factors_df.columns) actual_result = RiskContributionAnalysis.get_risk_contribution_optimised(assets_rets=self.factors_df, weights_of_assets=weights) expected_result = pd.Series([0.328845104104390, 0.671154895895610], index=self.factors_df.columns) assert_series_equal(expected_result, actual_result) weights = pd.Series([0.25, 0.75], index=self.factors_df.columns) actual_result = RiskContributionAnalysis.get_risk_contribution_optimised(assets_rets=self.factors_df, weights_of_assets=weights) expected_result = pd.Series([0.139939367445589, 0.860060632554411], index=self.factors_df.columns) assert_series_equal(expected_result, actual_result)
def test_get_risk_contribution(self): weights = pd.Series([0.5, 0.5], index=self.factors_df.columns) actual_result = RiskContributionAnalysis.get_risk_contribution(factors_rets=self.factors_df, weigths_of_assets=weights, portfolio_rets=self.portfolio_tms) expected_result = pd.Series([0.32739478440485410, 0.672605215595146], index=self.factors_df.columns) assert_series_equal(expected_result, actual_result) weights = pd.Series([0.25, 0.75], index=self.factors_df.columns) actual_result = RiskContributionAnalysis.get_risk_contribution(factors_rets=self.factors_df, weigths_of_assets=weights, portfolio_rets=self.portfolio_tms) expected_result = pd.Series([0.139601453264340, 0.860398546735660], index=self.factors_df.columns) assert_series_equal(expected_result, actual_result)
def test_historical_price__multiple_tickers__multiple_fields__daily(self): self.current_time = str_to_date("2021-05-06 00:00:00.000000", DateFormat.FULL_ISO) # Test when the current day does not have the open price actual_bars = self.data_provider.historical_price( [self.ticker_1, self.ticker_2], PriceField.ohlcv(), 2, frequency=Frequency.DAILY) self.assertEqual(type(actual_bars), QFDataArray) assert_series_equal(actual_bars.dates.to_pandas(), date_range('2021-05-04', '2021-05-05', freq="D").to_series(), check_names=False)
def test_exponential_average(self): actual_smoothed_series = self.test_returns_tms.exponential_average() expected_smoothed_values = [0.01, 0.0194, 0.029364, 0.02056184, 0.0106337104, 0.000638022624, -0.00936171864256, -0.019361703118554, 0.0082382978128868, 0.028694297868773, 0.048721657872126, 0.040523299472328, 0.03063139796834, 0.0206378838781, 0.010638273032686, 0.00063829638196116, 0.0094382977829177, 0.028766297866975, 0.020525977872019, 0.038831558672321] expected_smoothed_series = SimpleReturnsSeries(data=expected_smoothed_values, index=self.return_dates.copy()) assert_series_equal(expected_smoothed_series, actual_smoothed_series) actual_smoothed_series = self.test_returns_tms.exponential_average(lambda_coeff=1) expected_smoothed_series = self.test_returns_tms assert_series_equal(expected_smoothed_series, actual_smoothed_series)
def test_rolling_time_window(self): actual_result = self.test_prices_df.rolling_time_window(window_length=2, step=1, func=lambda x: x.mean()) expected_values = [[1.5, 1.5, 1.5, 1.5, 1.5], [2.5, 2.5, 2.5, 2.5, 2.5], [3.5, 3.5, 3.5, 3.5, 3.5], [4.5, 4.5, 4.5, 4.5, 4.5]] expected_index = self.test_prices_df.index[-4:].copy(deep=True) expected_columns = ['a', 'b', 'c', 'd', 'e'] expected_result = QFDataFrame(expected_values, expected_index, expected_columns) assert_dataframes_equal(expected_result, actual_result, absolute_tolerance=1e-20) actual_result = self.test_prices_df.rolling_time_window(window_length=2, step=1, func=lambda x: x.mean().mean()) expected_values = [1.5, 2.5, 3.5, 4.5] expected_index = self.test_prices_df.index[-4:].copy(deep=True) expected_result = QFSeries(expected_values, expected_index) assert_series_equal(expected_result, actual_result, absolute_tolerance=1e-20)
def test_get_aggregate_returns_with_log_returns(self): test_returns = [0.01] * 22 dates = DatetimeIndex([ '2000-01-15', '2000-01-17', '2000-01-19', '2000-01-21', '2000-01-23', '2000-01-25', '2000-01-27', '2000-01-29', '2000-01-31', '2000-02-02', '2000-02-04', '2000-03-05', '2000-04-04', '2000-05-04', '2000-06-03', '2000-07-03', '2001-01-19', '2001-08-07', '2002-02-23', '2002-09-11', '2003-03-30', '2003-10-16' ]) log_returns_series = LogReturnsSeries(data=test_returns, index=dates) expected_result = log_returns_series.to_simple_returns() actual_result = get_aggregate_returns(log_returns_series, convert_to=Frequency.DAILY) assert_series_equal(expected_result, actual_result) expected_cumulative_returns = \ [0.01, 0.04, 0.03, 0.03, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01] expected_dates = DatetimeIndex([ '2000-01-14', '2000-01-21', '2000-01-28', '2000-02-04', '2000-03-03', '2000-04-07', '2000-05-05', '2000-06-02', '2000-07-07', '2001-01-19', '2001-08-10', '2002-02-22', '2002-09-13', '2003-03-28', '2003-10-17' ]) expected_result = LogReturnsSeries( data=expected_cumulative_returns, index=expected_dates).to_simple_returns() actual_result = get_aggregate_returns(log_returns_series, convert_to=Frequency.WEEKLY) assert_series_equal(expected_result, actual_result) expected_cumulative_returns = \ [0.09, 0.02, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01] expected_dates = DatetimeIndex([ '2000-01-31', '2000-02-29', '2000-03-31', '2000-04-30', '2000-05-31', '2000-06-30', '2000-07-31', '2001-01-31', '2001-08-31', '2002-02-28', '2002-09-30', '2003-03-31', '2003-10-31' ]) expected_result = LogReturnsSeries( data=expected_cumulative_returns, index=expected_dates).to_simple_returns() actual_result = get_aggregate_returns(log_returns_series, convert_to=Frequency.MONTHLY) assert_series_equal(expected_result, actual_result) expected_cumulative_returns = [0.16, 0.02, 0.02, 0.02] expected_dates = DatetimeIndex( ['2000-12-31', '2001-12-31', '2002-12-31', '2003-12-31']) expected_result = LogReturnsSeries( data=expected_cumulative_returns, index=expected_dates).to_simple_returns() actual_result = get_aggregate_returns(log_returns_series, convert_to=Frequency.YEARLY) assert_series_equal(expected_result, actual_result)
def test_get_price_aggregation_single_ticker(self): MarketOpenEvent.set_trigger_time({"hour": 17, "minute": 13, "second": 0, "microsecond": 0}) dp = PortaraDataProvider(self.futures_path, self.ticker, PriceField.Close, self.start_date, self.end_date, Frequency.MIN_1) prices = dp.get_price(self.ticker, PriceField.Close, self.start_date, self.end_date, Frequency.MIN_1) prices5 = dp.get_price(self.ticker, PriceField.Close, self.start_date, self.end_date, Frequency.MIN_5) prices15 = dp.get_price(self.ticker, PriceField.Close, self.start_date, self.end_date, Frequency.MIN_15) self.assertTrue(len(prices5)) self.assertEqual(type(prices5), PricesSeries) self.assertEqual(Frequency.infer_freq(prices5.index), Frequency.MIN_5) assert_series_equal(prices5, prices.resample('5T', origin=datetime(2021, 6, 17, 17, 13)).last().dropna(), check_names=False) self.assertTrue(len(prices15)) self.assertEqual(type(prices15), PricesSeries) self.assertEqual(Frequency.infer_freq(prices15.index), Frequency.MIN_15) assert_series_equal(prices15, prices.resample('15T', origin=datetime(2021, 6, 17, 17, 13)).last().dropna(), check_names=False)
def test_historical_price__single_ticker__single_field__daily(self): self.current_time = str_to_date("2021-05-03 00:00:00.000000", DateFormat.FULL_ISO) # Test when the current day does not have the open price actual_series = self.data_provider.historical_price( self.ticker_2, PriceField.Open, 2, frequency=Frequency.DAILY) expected_series = PricesSeries( data=[27, 29], index=[str_to_date('2021-05-01'), str_to_date('2021-05-02')]) assert_series_equal(actual_series, expected_series, check_names=False) # Test when the previous day does not have the open price actual_series = self.data_provider.historical_price( self.ticker_1, PriceField.Open, 2, frequency=Frequency.DAILY) expected_series = PricesSeries( data=[25, 31], index=[str_to_date('2021-05-01'), str_to_date('2021-05-03')]) assert_series_equal(actual_series, expected_series, check_names=False)
def test_get_aggregate_returns_with_simple_returns(self): test_returns = [1, 1, 1, 1] dates = DatetimeIndex(['2015-12-01', '2016-05-05', '2016-10-01', '2017-01-05']) simple_returns_series = SimpleReturnsSeries(data=test_returns, index=dates) expected_cumulative_returns = [1.0, 3.0, 1.0] expected_result = SimpleReturnsSeries(data=expected_cumulative_returns, index=DatetimeIndex([ '2015-12-31', '2016-12-31', '2017-12-31'])) actual_result = get_aggregate_returns(simple_returns_series, convert_to=Frequency.YEARLY) assert_series_equal(expected_result, actual_result) expected_result = SimpleReturnsSeries(data=[1, 1, 1, 1], index=DatetimeIndex([ '2015-12-31', '2016-05-31', '2016-10-31', '2017-01-31'])) actual_result = get_aggregate_returns(simple_returns_series, convert_to=Frequency.MONTHLY) assert_series_equal(expected_result, actual_result) actual_result = get_aggregate_returns(simple_returns_series, convert_to=Frequency.MONTHLY, multi_index=True) actual_result = actual_result.unstack() self.assertEqual(actual_result[1].values[2], 1.0) self.assertEqual(actual_result[5].values[1], 1.0) self.assertEqual(actual_result[10].values[1], 1.0) self.assertEqual(actual_result[12].values[0], 1.0)
def test_get_values_for_common_dates(self): data = range(6) dates1 = DatetimeIndex([ '2014-12-31', '2015-01-02', '2015-01-04', '2015-01-05', '2015-01-09', '2015-01-10' ]) dates2 = DatetimeIndex([ '2015-02-01', '2015-01-02', '2015-01-03', '2015-01-04', '2015-01-05', '2015-01-10' ]) series1 = QFSeries(data=data, index=dates1, name='Series 1') series2 = QFSeries(data=data, index=dates2, name='Series 2') data_2d = array([data, data]).transpose() dataframe1 = QFDataFrame( data=data_2d, index=dates2, columns=['DataFrame Col. A', 'DataFrame Col. B']) expected_index = DatetimeIndex( ['2015-01-02', '2015-01-04', '2015-01-05', '2015-01-10']) expected_data1 = [1, 2, 3, 5] expected_series1 = QFSeries(data=expected_data1, index=expected_index, name='Series 1') expected_data2 = [1, 3, 4, 5] expected_series2 = QFSeries(data=expected_data2, index=expected_index, name='Series 2') expected_dataframe = QFDataFrame( data=array([expected_data2, expected_data2]).transpose(), index=expected_index, columns=['DataFrame Col. A', 'DataFrame Col. B']) actual_series1, actual_series2, actual_dataframe = get_values_for_common_dates( series1, series2, dataframe1) assert_series_equal(expected_series1, actual_series1) assert_series_equal(expected_series2, actual_series2) assert_dataframes_equal(expected_dataframe, actual_dataframe)
def test_make_parity_boxes(self): abs_tolerance = 0.0005 actual_boxes = self.risk_parity_boxes_factory.make_parity_boxes(self.start_date, self.end_date) datetime_index = pd.DatetimeIndex([ '2017-10-03', '2017-10-04', '2017-10-05', '2017-10-06', '2017-10-09', '2017-10-10', '2017-10-11', '2017-10-12', '2017-10-13', '2017-10-16', '2017-10-17', '2017-10-18', '2017-10-19', '2017-10-20', '2017-10-23', '2017-10-24', '2017-10-25', '2017-10-26', '2017-10-27', '2017-10-30', '2017-10-31', '2017-11-01' ]) expected_series = SimpleReturnsSeries(index=datetime_index, data=[ 0.000668214, 0.000835684, 0.000837076, -0.001577371, 0.000934, 0.002332372, 0.000723187, 0.000714223, 0.002511958, -0.00039049, -0.000812991, -0.000116197, 0.0011223, -0.001970612, -0.000243163, -0.000622247, 0.000292873, -0.001195635, 0.002011089, 0.002190187, 7.02049E-05, 0.000546751 ]) actual_series = actual_boxes.get_series(growth=ChangeDirection.RISING, inflation=ChangeDirection.RISING) assert_series_equal(expected_series, actual_series, absolute_tolerance=abs_tolerance) expected_series = SimpleReturnsSeries(index=datetime_index, data=[ 0.00214062368, 0.00011823259, 0.00133745897, -0.00093319962, .0, 0.00126311759, 0.00040289465, -0.00051413454, 0.00268699427, -0.00018594003, 0.00017342217, -0.00062892417, 0.00109962909, 0.00034010165, -0.00100080029, -0.0008813078, -0.00345021469, 0.00057545608, 0.0049085509, 0.00068356544, -0.00038338606, -0.00010546472 ]) actual_series = actual_boxes.get_series(growth=ChangeDirection.RISING, inflation=ChangeDirection.FALLING) assert_series_equal(expected_series, actual_series, absolute_tolerance=abs_tolerance) expected_series = SimpleReturnsSeries(index=datetime_index, data=[ 0.00075094743, 0.00102506202, -0.00116334637, 0.00086457088, 0.001030, 0.00202367433, 0.00069925268, 0.00124515552, 0.00178121325, -0.00337692323, -0.00195857117, -0.00094960523, 0.00162098426, -0.00199096335, 0.00042216467, -0.00137335971, -0.0010796149, -0.00136642671, 0.00247283233, 0.00223942762, -0.00063914336, 0.00046975 ]) actual_series = actual_boxes.get_series(growth=ChangeDirection.FALLING, inflation=ChangeDirection.RISING) assert_series_equal(expected_series, actual_series, absolute_tolerance=abs_tolerance) expected_series = SimpleReturnsSeries(index=datetime_index, data=[ 0.00112748921, 0.0005160599, -0.00222551401, 0.00103350015, 0.002442, 0.00115561595, 0.00162539269, 0.00111385182, 0.00464585854, -0.00296358368, -0.00262220629, -0.00270699558, 0.00275822114, -0.00509161628, 0.00107539045, -0.00342160737, -0.00093475391, -0.00330513788, 0.003736121, 0.00322371024, -0.00155485155, 0.00004935567 ]) actual_series = actual_boxes.get_series(growth=ChangeDirection.FALLING, inflation=ChangeDirection.FALLING) assert_series_equal(expected_series, actual_series, absolute_tolerance=abs_tolerance)
def test_log_returns_to_simple_returns(self): expected_tms = self.test_simple_returns_tms actual_tms = self.test_log_returns_tms.to_simple_returns() assert_series_equal(expected_tms, actual_tms)
def test_portfolio_leverage1(self): portfolio, dh, timer = self.get_portfolio_and_data_handler() expected_leverage_series = QFSeries() nav = self.initial_cash contract = self.fut_contract position = None def record_leverage(): expected_leverage_series[timer.now()] = position.total_exposure() / nav # Empty portfolio portfolio.update(record=True) expected_leverage_series[self.start_time] = 0 # Buy contract self._shift_timer_to_next_day(timer) transaction_1 = Transaction(timer.now(), contract, quantity=50, price=250, commission=7) portfolio.transact_transaction(transaction_1) self.data_handler_prices = self.prices_series portfolio.update(record=True) position = portfolio.open_positions_dict[contract] # Compute the leverage pnl = contract.contract_size * transaction_1.quantity * (position.current_price - transaction_1.price) nav += pnl - transaction_1.commission record_leverage() # Contract goes up in value self._shift_timer_to_next_day(timer) self.data_handler_prices = self.prices_up portfolio.update(record=True) # Compute the leverage price_after_increase = position.current_price pnl = contract.contract_size * transaction_1.quantity * (price_after_increase - transaction_1.price) nav = self.initial_cash + pnl - transaction_1.commission record_leverage() # Sell part of the contract self._shift_timer_to_next_day(timer) transaction_2 = Transaction(timer.time, contract, quantity=-30, price=position.current_price, commission=9) portfolio.transact_transaction(transaction_2) self.data_handler_prices = self.prices_up portfolio.update(record=True) # Compute the leverage pnl = (transaction_2.price - price_after_increase) * transaction_2.quantity * contract.contract_size nav += pnl - transaction_2.commission record_leverage() # Price goes down self._shift_timer_to_next_day(timer) self.data_handler_prices = self.prices_down portfolio.update(record=True) pnl = contract.contract_size * position.quantity() * (position.current_price - transaction_2.price) nav += pnl record_leverage() leverage_tms = portfolio.leverage_series() assert_series_equal(expected_leverage_series, leverage_tms)
def test_prices_to_log_returns(self): actual_log_returns_tms = self.test_prices_tms.to_log_returns() expected_log_returns_tms = self.test_log_returns_tms assert_series_equal(expected_log_returns_tms, actual_log_returns_tms)
def test_simple_returns_to_prices(self): expected_tms = self.test_prices_tms actual_tms = self.test_simple_returns_tms.to_prices(initial_price=100) assert_series_equal(expected_tms, actual_tms, absolute_tolerance=1e-5)
def test_portfolio_leverage2(self): expected_values = [] expected_dates = [] # empty portfolio portfolio, dh, timer = self.get_portfolio_and_data_handler() portfolio.update(record=True) expected_values.append(0) expected_dates.append(self.start_time) # buy contract quantity = 500 price = 120 commission1 = 7 new_time = timer.time + RelativeDelta(days=1) portfolio.transact_transaction(Transaction(new_time, self.contract, quantity, price, commission1)) timer.set_current_time(new_time) self.data_handler_prices = self.prices_series portfolio.update(record=True) gross_value = quantity * price pnl = quantity * (120 - 120) nav = self.initial_cash + pnl - commission1 expected_values.append(gross_value / nav) expected_dates.append(new_time) # contract goes up in value new_time = timer.time + RelativeDelta(days=1) timer.set_current_time(new_time) self.data_handler_prices = self.prices_up portfolio.update(record=True) gross_value = quantity * 130 pnl = quantity * (130 - 120) nav = self.initial_cash + pnl - commission1 expected_values.append(gross_value / nav) expected_dates.append(new_time) # sell part of the contract quantity = -300 price = 130 commission2 = 9 new_time = timer.time + RelativeDelta(days=1) portfolio.transact_transaction(Transaction(new_time, self.contract, quantity, price, commission2)) timer.set_current_time(new_time) self.data_handler_prices = self.prices_up portfolio.update(record=True) gross_value = 200 * 130 nav = nav - commission2 expected_values.append(gross_value / nav) expected_dates.append(new_time) # price goes down new_time = timer.time + RelativeDelta(days=1) timer.set_current_time(new_time) self.data_handler_prices = self.prices_down portfolio.update(record=True) gross_value = 200 * 100 pnl1 = 300 * (130 - 120) pnl2 = 200 * (100 - 120) nav = self.initial_cash + pnl1 + pnl2 - commission1 - commission2 expected_values.append(gross_value / nav) expected_dates.append(new_time) leverage_tms = portfolio.leverage_series() expected_tms = QFSeries(data=expected_values, index=expected_dates) assert_series_equal(expected_tms, leverage_tms)