예제 #1
0
def test_leg_valuations(mocker):
    with MockCalc(mocker):
        # children legs return values
        _, r1, f1 = get_attributes(mcb, risk.FXSpot)

    assert isinstance(r1.futures[0].result(), DataFrameWithInfo)
    assert 'path' in f1.columns
예제 #2
0
def test_exit_action_bytradename(mocker):
    with MockCalc(mocker):

        start_date = date(2021, 12, 6)
        end_date = date(2021, 12, 10)

        # Define trade
        irswap1 = IRSwap(PayReceive.Receive,
                         '10y',
                         Currency.USD,
                         notional_amount=1e5,
                         name='swap1')
        irswap2 = IRSwap(PayReceive.Pay,
                         '5y',
                         Currency.USD,
                         notional_amount=1e5,
                         name='swap2')

        trig_req_add = PeriodicTriggerRequirements(start_date=start_date,
                                                   end_date=end_date,
                                                   frequency='1b')
        trig_req_exit = PeriodicTriggerRequirements(start_date=start_date,
                                                    end_date=end_date,
                                                    frequency='2b')
        actions_add = AddTradeAction([irswap1, irswap2])
        actions_exit = ExitTradeAction('swap1')

        triggers = [
            PeriodicTrigger(trig_req_add, actions_add),
            PeriodicTrigger(trig_req_exit, actions_exit)
        ]
        strategy = Strategy(None, triggers)

        # run backtest daily
        engine = GenericEngine()
        # backtest = engine.run_backtest(strategy, start=start_date, end=end_date, frequency='1b', show_progress=True)
        backtest = engine.run_backtest(strategy,
                                       states=[
                                           date(2021, 12, 6),
                                           date(2021, 12, 7),
                                           date(2021, 12, 8),
                                           date(2021, 12, 9),
                                           date(2021, 12, 10)
                                       ],
                                       end=end_date,
                                       show_progress=True)

        trade_ledger = backtest.trade_ledger().to_dict('index')

        assert trade_ledger['Action1_swap1_2021-12-06']['Open'] == date(
            2021, 12, 6)
        assert trade_ledger['Action1_swap1_2021-12-06']['Close'] == date(
            2021, 12, 6)
        assert trade_ledger['Action1_swap1_2021-12-07']['Open'] == date(
            2021, 12, 7)
        assert trade_ledger['Action1_swap1_2021-12-07']['Close'] == date(
            2021, 12, 8)
        assert trade_ledger['Action1_swap2_2021-12-06']['Status'] == 'open'
        assert trade_ledger['Action1_swap2_2021-12-07']['Status'] == 'open'
        assert trade_ledger['Action1_swap2_2021-12-10']['Status'] == 'open'
예제 #3
0
def test_backtothefuture_pricing(mocker):
    with MockCalc(mocker):
        swap1 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.01, name='swap1')
        swap2 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.02, name='swap2')
        swap3 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.03, name='swap3')

        portfolio = Portfolio((swap1, swap2, swap3))
        pricing_date = dt.date(2021, 2, 10)
        with PricingContext(pricing_date=pricing_date):
            with BackToTheFuturePricingContext(dates=business_day_offset(
                    pricing_date, [-1, 0, 1], roll='forward')) as hpc:
                risk_key = hpc._PricingContext__risk_key(
                    risk.DollarPrice, swap1.provider)
                results = portfolio.calc(risk.DollarPrice)

    expected = risk.SeriesWithInfo(
        pd.Series(
            data=[-22711963.80864744, -22655907.930484552, -21582551.58922608],
            index=business_day_offset(pricing_date, [-1, 0, 1],
                                      roll='forward')),
        risk_key=historical_risk_key(risk_key),
    )

    actual = results[risk.DollarPrice].aggregate()

    assert actual.equals(expected)
예제 #4
0
def test_one_portfolio(mocker):
    with MockCalc(mocker):
        _, r1, f1 = get_attributes(eur_port, risk.Price)
        _, r2, f2 = get_attributes(eur_port, (risk.Price, risk.DollarPrice))
        _, _, f3 = get_attributes(Portfolio(swap_1, name='swap_1'),
                                  (risk.Price, risk.DollarPrice))

    price_values_test(r1, f1)
    price_values_test(r2, f2)

    default_pivot_table_test(r1)
    default_pivot_table_test(r2)

    # test slicing
    # slice one risk measure
    sub_r1 = r1[risk.Price]
    assert sub_r1 == r1
    # slice one instrument
    sub_r2 = r2[swap_1].to_frame().values[0]
    assert all(sub_r2 == f3['value'].values)

    # test aggregate
    agg_r1 = r1.aggregate().to_frame()
    agg_r2 = r2.aggregate().to_frame().values[0]
    assert agg_r1 == sum(f1['value'].values)
    assert all(agg_r2 == [
        sum(f2.loc[f2['risk_measure'] == rm]['value'].values)
        for rm in [risk.Price, risk.DollarPrice]
    ])
예제 #5
0
def test_backtothefuture_pricing(mocker):
    with MockCalc(mocker):
        swap1 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.01, name='swap1')
        swap2 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.02, name='swap2')
        swap3 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.03, name='swap3')

        portfolio = Portfolio((swap1, swap2, swap3))
        pricing_date = dt.date(2020, 10, 7)
        with PricingContext(pricing_date=pricing_date):
            with BackToTheFuturePricingContext(dates=business_day_offset(
                    pricing_date, [-1, 0, 1], roll='forward')) as hpc:
                risk_key = hpc._PricingContext__risk_key(
                    risk.DollarPrice, swap1.provider)
                results = portfolio.calc(risk.DollarPrice)

    expected = risk.SeriesWithInfo(
        pd.Series(
            data=[-35280379.86540368, -35348910.76427929, -30830994.939595155],
            index=business_day_offset(pricing_date, [-1, 0, 1],
                                      roll='forward')),
        risk_key=risk_key.ex_date_and_market,
    )

    actual = results[risk.DollarPrice].aggregate()

    assert actual.equals(expected)
예제 #6
0
def test_historical_pricing(mocker):
    with MockCalc(mocker):
        swap1 = IRSwap('Pay', '10y', 'USD', fixed_rate='ATM+1', name='10y@a+1')
        swap2 = IRSwap('Pay', '10y', 'USD', fixed_rate='ATM+2', name='10y@a+2')
        swap3 = IRSwap('Pay', '10y', 'USD', fixed_rate='ATM+3', name='10y@a+3')

        portfolio = Portfolio((swap1, swap2, swap3))
        dates = (dt.date(2021, 2, 9), dt.date(2021, 2, 10), dt.date(2021, 2, 11))

        with HistoricalPricingContext(dates=dates) as hpc:
            risk_key = hpc._PricingContext__risk_key(risk.DollarPrice, swap1.provider)
            results = portfolio.calc((risk.DollarPrice, risk.IRDelta))

        expected = risk.SeriesWithInfo(
            pd.Series(
                data=[-580316.7895084377, -580373.4091600645, -580811.1441974249],
                index=[dt.date(2021, 2, 9), dt.date(2021, 2, 10), dt.date(2021, 2, 11)]
            ),
            risk_key=historical_risk_key(risk_key), )

        assert results.dates == dates
        actual = results[risk.DollarPrice].aggregate()
        assert actual.equals(expected)

        assert (results[dt.date(2021, 2, 9)][risk.DollarPrice]['10y@a+1'] ==
                results[risk.DollarPrice][dt.date(2021, 2, 9)]['10y@a+1'])
        assert (results[dt.date(2021, 2, 9)][risk.DollarPrice]['10y@a+1'] ==
                results[risk.DollarPrice]['10y@a+1'][dt.date(2021, 2, 9)])
        assert (results[dt.date(2021, 2, 9)][risk.DollarPrice]['10y@a+1'] ==
                results['10y@a+1'][risk.DollarPrice][dt.date(2021, 2, 9)])
        assert (results[dt.date(2021, 2, 9)][risk.DollarPrice]['10y@a+1'] ==
                results['10y@a+1'][dt.date(2021, 2, 9)][risk.DollarPrice])
        assert (results[dt.date(2021, 2, 9)][risk.DollarPrice]['10y@a+1'] ==
                results[dt.date(2021, 2, 9)]['10y@a+1'][risk.DollarPrice])
예제 #7
0
def test_aggregation_with_diff_risk_keys(mocker):
    with MockCalc(mocker):
        portfolio1 = Portfolio([
            IRSwaption('Pay',
                       '10y',
                       'EUR',
                       expiration_date='3m',
                       name='EUR3m10ypayer')
        ])
        portfolio2 = Portfolio([
            IRSwaption('Pay',
                       '10y',
                       'EUR',
                       expiration_date='6m',
                       name='EUR6m10ypayer')
        ])

        with PricingContext(csa_term='EUR-OIS', visible_to_gs=True):
            r1 = portfolio1.price()
        with PricingContext(csa_term='EUR-EuroSTR'):
            r2 = portfolio2.price()

        combined_result = r1 + r2

    with pytest.raises(ValueError):
        combined_result.aggregate()

    assert isinstance(combined_result.aggregate(allow_mismatch_risk_keys=True),
                      float)
예제 #8
0
def test_aggregation_with_empty_measures(mocker):
    with MockCalc(mocker):
        swaptions = (IRSwaption(notional_currency='EUR',
                                termination_date='7y',
                                expiration_date='1y',
                                pay_or_receive='Receive',
                                strike='ATM+35',
                                name='EUR 1y7y'),
                     IRSwaption(notional_currency='EUR',
                                termination_date='10y',
                                expiration_date='2w',
                                pay_or_receive='Receive',
                                strike='ATM+50',
                                name='EUR 2w10y'))
        portfolio = Portfolio(swaptions)

        from_date = dt.date(2021, 11, 18)
        to_date = dt.date(2021, 11, 19)
        explain_2d = PnlExplain(CloseMarket(date=to_date))

        with PricingContext(pricing_date=from_date, visible_to_gs=True):
            portfolio.resolve()
            result_explain = portfolio.calc(explain_2d)

        total_risk = aggregate_risk(result_explain[explain_2d])['value'].sum()
        risk_swaption_1 = result_explain[0]['value'].sum()
        risk_swaption_2 = result_explain[1]['value'].sum()

        assert total_risk == risk_swaption_1 + risk_swaption_2
예제 #9
0
def test_unnamed_portfolio(mocker):
    unnamed_1 = Portfolio((swap_1, swap_2))
    unnamed_2 = Portfolio((swap_3, swap_4))
    unnamed = Portfolio((unnamed_1, unnamed_2))
    with MockCalc(mocker):
        res = unnamed.calc(risk.IRFwdRate)
        df = res.to_frame()
        assert len(df) == 2
        assert list(df.index) == ['Portfolio_0', 'Portfolio_1']
        assert list(df.columns) == ['5y', '10y']
예제 #10
0
def test_single_instrument_new_mock(mocker):
    with MockCalc(mocker):
        with PricingContext(pricing_date=dt.date(2020, 10, 15)):
            swap1 = IRSwap('Pay', '10y', 'USD', name='swap1')

            portfolio = Portfolio(swap1)
            fwd: PortfolioRiskResult = portfolio.calc(risk.IRFwdRate)

        assert portfolio.paths('swap1') == (PortfolioPath(0), )
        assert tuple(map(lambda x: round(x, 6), fwd)) == (0.007512, )
        assert round(fwd.aggregate(), 2) == 0.01
        assert round(fwd[swap1], 6) == 0.007512
예제 #11
0
def test_currency_params(mocker):
    price = risk.Price
    myr_price = risk.Price(currency="MYR")

    with MockCalc(mocker):
        res1 = swap_1.calc(myr_price)
        res2 = swap_1.calc(price)
        res3 = swap_1.calc((price, myr_price))

    assert (res1 != res2)
    assert (res3[price] == res2)
    assert (res3[myr_price] == res1)
예제 #12
0
def test_single_instrument(mocker):
    with MockCalc(mocker):
        swap1 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.0, name='10y@0')

        portfolio = Portfolio(swap1)
        assert portfolio.paths('10y@0') == (PortfolioPath(0), )

        with PricingContext(pricing_date=dt.date(2020, 10, 15)):
            prices: PortfolioRiskResult = portfolio.dollar_price()
        assert tuple(map(lambda x: round(x, 0), prices)) == (7391258.0, )
        assert round(prices.aggregate(), 0) == 7391258.0
        assert round(prices[swap1], 0) == 7391258.0
예제 #13
0
def test_dated_risk_values(mocker):
    with MockCalc(mocker):
        _, res1, frame1 = get_attributes(port, risk.Price, 'Multiple')
        _, res2, frame2 = get_attributes(port1, (risk.DollarPrice, risk.Price),
                                         'Multiple')
        _, res3, frame3 = get_attributes(port1, risk.Price)
        _, res4, frame4 = get_attributes(port1, (risk.DollarPrice, risk.Price))
        _, res5, frame5 = get_attributes(gbp_port,
                                         (risk.DollarPrice, risk.Price),
                                         'Multiple')
        _, res6, frame6 = get_attributes(jpy_port, risk.Price, 'Multiple')

    price_values_test(res1, frame1, 'dated')
    price_values_test(res2, frame2, 'dated')
    price_values_test(res5, frame5, 'dated')
    price_values_test(res6, frame6, 'dated')

    default_pivot_table_test(res1, 'dated')
    default_pivot_table_test(res2, 'dated')
    default_pivot_table_test(res5, 'dated')
    default_pivot_table_test(res6, 'dated')

    # test slicing
    sub_res1 = res1[risk.Price]
    assert sub_res1 == res1

    # slice one date
    slice_date_res2 = res2[date(2020, 1, 14)]
    assert all(slice_date_res2.to_frame(None, None, None) == frame4)
    slice_date_res3 = slice_date_res2[risk.Price]
    assert all(slice_date_res3.to_frame(None, None, None) == frame3)

    # slice dates
    slice_date_res2 = res2[[date(2020, 1, 14), date(2020, 1, 15)]]
    assert all(slice_date_res2.to_frame(None, None, None) == frame2)

    # test aggregate
    agg_res5 = res5.aggregate().to_frame(None, None, None)

    def filter_lambda(x):
        return (x['risk_measure'] == risk.DollarPrice) & (x['dates'] == date(
            2020, 1, 14))

    manual_agg_r5 = frame5.loc[frame5.apply(filter_lambda,
                                            axis=1)]['value'].values.sum()
    filter_agg_res5 = agg_res5.loc[agg_res5.apply(filter_lambda,
                                                  axis=1)]['value'].values[0]
    assert filter_agg_res5 == manual_agg_r5

    sub_res6 = res6.aggregate().to_frame().loc[date(2020, 1, 14)].values[0]
    manual_agg_r6 = frame6.loc[frame6['dates'] == date(
        2020, 1, 14)]['value'].values.sum()
    assert sub_res6 == manual_agg_r6
예제 #14
0
def test_unsupported_error_datums(mocker):
    with MockCalc(mocker):
        f1 = eur_port.calc(risk.IRAnnualImpliedVol).to_frame()
        _, _, f2 = get_attributes(swap_port1, risk.IRAnnualImpliedVol)
        _, _, f3 = get_attributes(swaption_port1, risk.IRAnnualImpliedVol)
        _, _, f4 = get_attributes(swaption_port3, risk.IRAnnualImpliedVol)

    # assert that unsupported datums do not appear to_frame()
    assert f1 is None
    assert all(f2['value'] == f3['value'])

    # assert that errorvalue appears in to_frame()
    assert isinstance(f4['value'].values[0], ErrorValue)
예제 #15
0
def test_resolve_to_frame(mocker):
    # makes sure resolving portfolio doesn't break to_frame
    with MockCalc(mocker):
        _, r1, f1 = get_attributes(eur_port, risk.Price, resolve=True)
        _, r2, f2 = get_attributes(port1, risk.Price, resolve=True)
        _, r3, f3 = get_attributes(jpy_port,
                                   risk.Price,
                                   'RollFwd',
                                   resolve=True)
        _, r4, f4 = get_attributes(port1,
                                   risk.Price,
                                   'CurveScen1',
                                   resolve=True)
예제 #16
0
def test_cashflows_risk(mocker):
    with MockCalc(mocker):
        _, _, frame1 = get_attributes(eur_port, risk.Cashflows)
        _, _, frame2 = get_attributes(port1, risk.Cashflows)

    assert 'payment_date' in frame1.columns.values
    assert 'payment_date' in frame2.columns.values

    assert np.unique(frame1.risk_measure.values)[0] == risk.Cashflows
    assert np.unique(frame2.risk_measure.values)[0] == risk.Cashflows

    assert 'instrument_name' in frame1.columns.values
    assert 'instrument_name' in frame2.columns.values
    assert 'portfolio_name_0' in frame2.columns.values
예제 #17
0
def test_hedge_action_risk_trigger(mocker):
    with MockCalc(mocker):
        start_date = date(2021, 12, 1)
        # end_date = date(2021, 12, 3)

        # Define trade
        call = FXOption(buy_sell='Buy',
                        option_type='Call',
                        pair='USDJPY',
                        strike_price='ATMF',
                        notional_amount=1e5,
                        expiration_date='2y',
                        name='2y_call')

        hedge_risk = FXDelta(aggregation_level='Type')
        fwd_hedge = FXForward(pair='USDJPY',
                              settlement_date='2y',
                              notional_amount=1e5,
                              name='2y_forward')

        trig_req = RiskTriggerRequirements(risk=hedge_risk,
                                           trigger_level=0,
                                           direction=TriggerDirection.ABOVE)
        action_hedge = HedgeAction(hedge_risk, fwd_hedge, '2b')

        triggers = StrategyRiskTrigger(trig_req, action_hedge)

        with PricingContext(pricing_date=start_date):
            fut = call.resolve(in_place=False)

        call = fut.result()

        strategy = Strategy(call, triggers)

        # run backtest daily
        engine = GenericEngine()
        # backtest = engine.run_backtest(strategy, start=start_date, end=end_date, frequency='1b', show_progress=True)
        backtest = engine.run_backtest(
            strategy,
            states=[date(2021, 12, 1),
                    date(2021, 12, 2),
                    date(2021, 12, 3)],
            show_progress=True)
        summary = backtest.result_summary
        assert len(summary) == 3
        assert round(summary[hedge_risk].sum()) == 0
        assert round(summary['Cumulative Cash'].sum()) == -7090
        assert Price in summary.columns
예제 #18
0
def test_duplicate_instrument(mocker):
    with MockCalc(mocker):
        swap1 = IRSwap('Pay', '1y', 'EUR', name='EUR1y')
        swap2 = IRSwap('Pay', '2y', 'EUR', name='EUR2y')
        swap3 = IRSwap('Pay', '3y', 'EUR', name='EUR3y')

        portfolio = Portfolio((swap1, swap2, swap3, swap1))
        assert portfolio.paths('EUR1y') == (PortfolioPath(0), PortfolioPath(3))
        assert portfolio.paths('EUR2y') == (PortfolioPath(1), )
        with PricingContext(pricing_date=dt.date(2020, 10, 15)):
            fwds: PortfolioRiskResult = portfolio.calc(risk.IRFwdRate)

        assert tuple(map(lambda x: round(x, 6),
                         fwds)) == (-0.005378, -0.005224, -0.00519, -0.005378)
        assert round(fwds.aggregate(), 6) == -0.02117
        assert round(fwds[swap1], 6) == -0.005378
예제 #19
0
def test_finite_difference_params(mocker):
    nok_delta = risk.IRDelta(currency="NOK")
    local_ccy_delta = risk.IRDelta(currency='local')

    with MockCalc(mocker):
        res3 = swap_1.calc(risk.IRDelta)
        res5 = swap_1.calc((risk.Price, nok_delta))
        res6 = swap_1.calc((local_ccy_delta, nok_delta))
        res7 = swap_1.calc(
            risk.IRDelta(aggregation_level=AggregationLevel.Asset))

    assert isinstance(res5[risk.Price], FloatWithInfo)
    assert isinstance(res5[nok_delta], DataFrameWithInfo)
    assert res6[local_ccy_delta]['value'].size != res6[nok_delta]['value'].size
    assert res6[local_ccy_delta]['value'].size != res3['value'].size
    assert res6[nok_delta]['value'].size != res3['value'].size
    assert res7['mkt_asset'].size == 2
예제 #20
0
def test_mkt_trigger_data_sources(mocker):
    with MockCalc(mocker):
        s = pd.Series({
            date(2021, 10, 1): 0.984274,
            date(2021, 10, 4): 1.000706,
            date(2021, 10, 5): 1.044055,
            date(2021, 10, 6): 1.095361,
            date(2021, 10, 7): 1.129336,
            date(2021, 10, 8): 1.182954,
            date(2021, 10, 12): 1.200108,
            date(2021, 10, 13): 1.220607,
            date(2021, 10, 14): 1.172837,
            date(2021, 10, 15): 1.163660,
            date(2021, 10, 18): 1.061084,
            date(2021, 10, 19): 1.025012,
            date(2021, 10, 20): 1.018035,
            date(2021, 10, 21): 1.080751,
            date(2021, 10, 22): 1.069340,
            date(2021, 10, 25): 1.033413
        })

        action = AddTradeAction(
            IRSwaption(notional_currency='USD',
                       expiration_date='1y',
                       termination_date='1y'), 'expiration_date')
        data_source = GenericDataSource(s, MissingDataStrategy.fill_forward)
        mkt_trigger = MktTrigger(
            MktTriggerRequirements(data_source, 1.1, TriggerDirection.ABOVE),
            action)
        strategy = Strategy(None, mkt_trigger)

        engine = GenericEngine()

        # backtest = engine.run_backtest(strategy, start=date(2021, 10, 1), end=date(2021, 10, 25), frequency='1b',
        #                                show_progress=True)
        backtest = engine.run_backtest(strategy,
                                       states=s.index,
                                       show_progress=True)

        summary = backtest.result_summary
        ledger = backtest.trade_ledger()
        assert len(summary) == 12
        assert len(ledger) == 6
        assert round(summary[Price].sum()) == 25163614
        assert round(summary['Cumulative Cash'].sum()) == -2153015
예제 #21
0
def test_historical_pricing(mocker):
    with MockCalc(mocker):
        swap1 = IRSwap('Pay', '10y', 'USD', fixed_rate='ATM+1', name='10y@a+1')
        swap2 = IRSwap('Pay', '10y', 'USD', fixed_rate='ATM+2', name='10y@a+2')
        swap3 = IRSwap('Pay', '10y', 'USD', fixed_rate='ATM+3', name='10y@a+3')

        portfolio = Portfolio((swap1, swap2, swap3))
        dates = (dt.date(2019, 10, 7), dt.date(2019, 10,
                                               8), dt.date(2019, 10, 9))

        with HistoricalPricingContext(dates=dates) as hpc:
            risk_key = hpc._PricingContext__risk_key(risk.DollarPrice,
                                                     swap1.provider)
            results = portfolio.calc((risk.DollarPrice, risk.IRDelta))

        expected = risk.SeriesWithInfo(
            pd.Series(data=[
                -564854.3640043903, -565604.2636791412, -564751.5121349357
            ],
                      index=[
                          dt.date(2019, 10, 7),
                          dt.date(2019, 10, 8),
                          dt.date(2019, 10, 9)
                      ]),
            risk_key=risk_key.ex_date_and_market,
        )

        assert results.dates == dates
        actual = results[risk.DollarPrice].aggregate()
        assert actual.equals(expected)

        assert (results[dt.date(2019, 10, 9)][risk.DollarPrice]['10y@a+1'] ==
                results[risk.DollarPrice][dt.date(2019, 10, 9)]['10y@a+1'])
        assert (results[dt.date(2019, 10, 9)][risk.DollarPrice]['10y@a+1'] ==
                results[risk.DollarPrice]['10y@a+1'][dt.date(2019, 10, 9)])
        assert (results[dt.date(2019, 10, 9)][risk.DollarPrice]['10y@a+1'] ==
                results['10y@a+1'][risk.DollarPrice][dt.date(2019, 10, 9)])
        assert (results[dt.date(
            2019, 10,
            9)][risk.DollarPrice]['10y@a+1'] == results['10y@a+1'][dt.date(
                2019, 10, 9)][risk.DollarPrice])
        assert (results[dt.date(
            2019, 10, 9)][risk.DollarPrice]['10y@a+1'] == results[dt.date(
                2019, 10, 9)]['10y@a+1'][risk.DollarPrice])
예제 #22
0
def test_portfolio(mocker):

    with MockCalc(mocker):
        with PricingContext(pricing_date=dt.date(2020, 10, 15)):
            swap1 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.001, name='swap_10y@10bp')
            swap2 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.002, name='swap_10y@20bp')
            swap3 = IRSwap('Pay', '10y', 'USD', fixed_rate=0.003, name='swap_10y@30bp')

            portfolio = Portfolio((swap1, swap2, swap3))

            prices: PortfolioRiskResult = portfolio.dollar_price()
            result = portfolio.calc((risk.DollarPrice, risk.IRDelta))

        assert tuple(sorted(map(lambda x: round(x, 0), prices))) == (4439478.0, 5423405.0, 6407332.0)
        assert round(prices.aggregate(), 2) == 16270214.48
        assert round(prices[0], 0) == 6407332.0
        assert round(prices[swap2], 0) == 5423405.0
        assert round(prices['swap_10y@30bp'], 0) == 4439478.0

        assert tuple(map(lambda x: round(x, 0), result[risk.DollarPrice])) == (6407332.0, 5423405.0, 4439478.0)
        assert round(result[risk.DollarPrice].aggregate(), 0) == 16270214.0
        assert round(result[risk.DollarPrice]['swap_10y@30bp'], 0) == 4439478.0
        assert round(result[risk.DollarPrice]['swap_10y@30bp'], 0) == round(result['swap_10y@30bp'][risk.DollarPrice],
                                                                            0)

        assert round(result[risk.IRDelta].aggregate().value.sum(), 0) == 278977.0

        prices_only = result[risk.DollarPrice]
        assert tuple(map(lambda x: round(x, 0), prices)) == tuple(map(lambda x: round(x, 0), prices_only))

        swap4 = IRSwap('Pay', '10y', 'USD', fixed_rate=-0.001, name='swap_10y@-10bp')
        portfolio.append(swap4)
        assert len(portfolio.instruments) == 4

        extracted_swap = portfolio.pop('swap_10y@20bp')
        assert extracted_swap == swap2
        assert len(portfolio.instruments) == 3

        swap_dict = {'swap_5': swap1,
                     'swap_6': swap2,
                     'swap_7': swap3}

        portfolio = Portfolio(swap_dict)
        assert len(portfolio) == 3
예제 #23
0
def test_pricing_context(mocker):
    swap1 = IRSwap('Pay', '1y', 'EUR', name='EUR1y')
    future_date = business_day_offset(dt.date.today(), 10, roll='forward')
    with MockCalc(mocker):
        with RollFwd(date='10b', realise_fwd=True):
            market = swap1.market()

    with pytest.raises(ValueError):
        # cannot pass in future date into pricing context, use RollFwd instead
        with PricingContext(pricing_date=future_date):
            _ = swap1.calc(risk.Price)

        # cannot pass in market dated in the future into pricing context, use RollFwd instead
        with PricingContext(market=CloseMarket(date=future_date)):
            _ = swap1.calc(risk.Price)

        with PricingContext(market=OverlayMarket(base_market=CloseMarket(date=future_date, location='NYC'),
                                                 market_data=market.result())):
            _ = swap1.calc(risk.Price)
예제 #24
0
def test_nested_portfolio(mocker):
    with MockCalc(mocker):
        cols1, res1, frame1 = get_attributes(port1,
                                             (risk.DollarPrice, risk.Price))
        cols2, res2, frame2 = get_attributes(port,
                                             (risk.DollarPrice, risk.Price))
        _, swap1_6_res, frame3 = get_attributes(
            Portfolio((swap_1, swap_6), name='swap_1_6'), risk.DollarPrice)
        _, res4, frame4 = get_attributes(
            port1, (risk.DollarPrice, risk.Price, risk.Theta))

    price_values_test(res1, frame1)
    price_values_test(res2, frame2)
    dollar_eur_frame1 = frame1[(frame1['portfolio_name_0'] == 'EUR') & (
        frame1['risk_measure'] == risk.DollarPrice)]['value'].values
    dollar_eur_frame2 = frame2[(frame2['portfolio_name_0'] == 'EURGBP')
                               & (frame2['portfolio_name_1'] == 'EUR') &
                               (frame2['risk_measure']
                                == risk.DollarPrice)]['value'].values

    default_pivot_table_test(res1)
    default_pivot_table_test(res2)

    # test slicing
    # slice multiple instruments
    slice_res2 = res1[[swap_1, swap_6
                       ]][risk.DollarPrice].to_frame(None, None,
                                                     None)['value'].values
    assert all(
        slice_res2 == swap1_6_res.to_frame(None, None, None)['value'].values)

    sub_frame1 = res1[risk.DollarPrice][swap_1].to_frame()
    assert sub_frame1 == dollar_eur_frame1[0]
    assert sub_frame1 == dollar_eur_frame2[0]

    sub_frame2 = res2[eur_port][risk.DollarPrice].to_frame(
        None, None, None)['value'].values
    assert all(dollar_eur_frame1 == sub_frame2)
    assert all(dollar_eur_frame2 == sub_frame2)
    # slice multiple risk measures
    sub_res4 = res4[[risk.Price, risk.DollarPrice]]
    assert all(sub_res4.to_frame() == res1.to_frame())
예제 #25
0
def test_empty_calc_request(mocker):
    # when calc req is sent for rm that inst is insensitive to
    with MockCalc(mocker):
        _, r1, f1 = get_attributes(swap_port1, (risk.IRVega, risk.Price))
        _, r2, f2 = get_attributes(
            swap_port2, (risk.IRVega(aggregation_level=AggregationLevel.Asset),
                         risk.Price))
        _, r3, f3 = get_attributes(
            swap_port1, (risk.IRVega(aggregation_level=AggregationLevel.Asset,
                                     currency='local'), risk.Price))
        _, r4, f4 = get_attributes(swap_port2,
                                   (risk.Price, risk.IRVega(currency='local')))
        _, r5, f5 = get_attributes(swap_port2, (risk.Price, risk.IRVega),
                                   'Multiple')
        _, r6, f6 = get_attributes(
            swap_port1, (risk.IRVega(aggregation_level=AggregationLevel.Asset),
                         risk.Price), 'Multiple')
        _, r7, f7 = get_attributes(
            swap_port2, (risk.IRVega(aggregation_level=AggregationLevel.Asset,
                                     currency='local'), risk.Price),
            'Multiple')
        _, r8, f8 = get_attributes(swap_port1,
                                   (risk.IRVega(currency='local'), risk.Price),
                                   'Multiple')

    price_values_test(r1, f1)
    price_values_test(r2, f2)
    price_values_test(r3, f3)
    price_values_test(r4, f4)
    price_values_test(r5, f5, 'dated')
    price_values_test(r6, f6, 'dated')
    price_values_test(r7, f7, 'dated')
    price_values_test(r8, f8, 'dated')

    default_pivot_table_test(r1, 'has_bucketed')
    default_pivot_table_test(r2, 'has_bucketed')
    default_pivot_table_test(r3, 'has_bucketed')
    default_pivot_table_test(r4, 'has_bucketed')
    default_pivot_table_test(r5, 'has_bucketed')
    default_pivot_table_test(r6, 'has_bucketed')
    default_pivot_table_test(r7, 'has_bucketed')
    default_pivot_table_test(r8, 'has_bucketed')
예제 #26
0
def test_generic_engine_simple(mocker):
    with MockCalc(mocker):

        start_date = date(2021, 12, 1)
        # end_date = date(2021, 12, 3)

        # Define trade
        call = FXOption(buy_sell='Buy',
                        option_type='Call',
                        pair='USDJPY',
                        strike_price='ATMF',
                        notional_amount=1e5,
                        expiration_date='2y',
                        name='2y_call')

        # Periodic trigger: based on frequency
        freq = '1m'

        # trig_req = PeriodicTriggerRequirements(start_date=start_date, end_date=end_date, frequency=freq)
        trig_req = DateTriggerRequirements(dates=[start_date])
        actions = AddTradeAction(call, freq)

        # starting with empty portfolio (first arg to Strategy), apply actions on trig_req
        triggers = DateTrigger(trig_req, actions)

        strategy = Strategy(None, triggers)

        # run backtest daily
        engine = GenericEngine()
        # backtest = engine.run_backtest(strategy, start=start_date, end=end_date, frequency='1b', show_progress=True)
        backtest = engine.run_backtest(
            strategy,
            states=[date(2021, 12, 1),
                    date(2021, 12, 2),
                    date(2021, 12, 3)],
            show_progress=True)
        summary = backtest.result_summary
        assert len(summary) == 3
        assert round(summary[Price].sum()) == 2424
        assert round(summary['Cumulative Cash'].sum()) == 0
예제 #27
0
def test_portfolio_overrides(mocker):
    swap_1 = IRSwap("Pay", "5y", "EUR", fixed_rate=-0.005, name="5y")
    swap_2 = IRSwap("Pay", "10y", "EUR", fixed_rate=-0.005, name="10y")
    swap_3 = IRSwap("Pay", "5y", "GBP", fixed_rate=-0.005, name="5y")
    swap_4 = IRSwap("Pay", "10y", "GBP", fixed_rate=-0.005, name="10y")
    eur_port = Portfolio([swap_1, swap_2], name="EUR")
    gbp_port = Portfolio([swap_3, swap_4], name="GBP")

    # override instruments after portfolio construction
    for idx in range(len(eur_port)):
        eur_port[idx].fixed_rate = eur_port[idx].fixed_rate - 0.0005

    assert eur_port[swap_1] is not None

    with MockCalc(mocker):
        # override instruments after portfolio construction and resolution
        gbp_port.resolve()
        for idx in range(len(gbp_port)):
            gbp_port[idx].notional_amount = gbp_port[idx].notional_amount - 1

        with PricingContext(dt.date(2020, 1, 14)):
            r1 = eur_port.calc(risk.Price)
            r2 = eur_port.calc((risk.Price, risk.DollarPrice))
            r3 = gbp_port.calc(risk.Price)
            r4 = gbp_port.calc((risk.DollarPrice, risk.Price))

    assert gbp_port[swap_3] is not None

    assert r1[eur_port[0]] is not None
    assert r1['5y'] is not None
    assert r1.to_frame() is not None
    assert r2[eur_port[0]] is not None
    assert r2[risk.Price][0] is not None
    assert r2[0][risk.Price] is not None
    assert r3[gbp_port[0]] is not None
    assert r3.to_frame() is not None
    assert r4[gbp_port[0]] is not None
    assert r4[risk.DollarPrice][0] is not None
    assert r4[0][risk.DollarPrice] is not None
예제 #28
0
def test_diff_types_risk_measures(mocker):
    # when risk results from scalar and bucketed risk measures are be to tabulated together
    with MockCalc(mocker):
        _, res1, frame1 = get_attributes(eur_port, (risk.Price, risk.IRDelta))
        _, res2, frame2 = get_attributes(mixed_port,
                                         (risk.IRBasis, risk.Price))
        _, res3, frame3 = get_attributes(mixed_port, (risk.IRBasis(
            aggregation_level=AggregationLevel.Asset), risk.Price))
        _, res4, frame4 = get_attributes(eur_port, (risk.IRDelta, risk.Price),
                                         'Multiple')
        _, res5, frame5 = get_attributes(mixed_port,
                                         (risk.Price, risk.IRBasis),
                                         'Multiple')
        _, res6, frame6 = get_attributes(mixed_port, (risk.IRBasis(
            aggregation_level=AggregationLevel.Asset), risk.Price), 'Multiple')

    price_values_test(res1, frame1)
    price_values_test(res2, frame2)
    price_values_test(res3, frame3)
    price_values_test(res4, frame4, 'dated')
    price_values_test(res5, frame5, 'dated')
    price_values_test(res6, frame6, 'dated')

    default_pivot_table_test(res1, 'has_bucketed')
    default_pivot_table_test(res2, 'has_bucketed')
    default_pivot_table_test(res3, 'has_bucketed')
    default_pivot_table_test(res4, 'has_bucketed')
    default_pivot_table_test(res5, 'has_bucketed')
    default_pivot_table_test(res6, 'has_bucketed')

    # test aggregate
    sub_res1 = res1.aggregate().to_frame()
    assert all(sub_res1.loc[risk.IRDelta]['value'].values == res1[
        risk.IRDelta].aggregate().to_frame()['value'].values)
    assert sub_res1.loc[risk.Price]['value'] == res1[
        risk.Price].aggregate().to_frame()
예제 #29
0
def test_results_with_resolution(mocker):
    with MockCalc(mocker):

        swap1 = IRSwap('Pay', '10y', 'USD', name='swap1')
        swap2 = IRSwap('Pay', '10y', 'GBP', name='swap2')
        swap3 = IRSwap('Pay', '10y', 'EUR', name='swap3')

        portfolio = Portfolio((swap1, swap2, swap3))

        with PricingContext(pricing_date=dt.date(2020, 10, 15)):
            result = portfolio.calc((risk.DollarPrice, risk.IRDelta))

        # Check that we've got results
        assert result[swap1][risk.DollarPrice] is not None

        # Now resolve portfolio and assert that we can still get the result

        orig_swap1 = swap1.clone()

        with PricingContext(pricing_date=dt.date(2020, 10, 15)):
            portfolio.resolve()

        # Assert that the resolved swap is indeed different and that we can retrieve results by both

        assert swap1 != orig_swap1
        assert result[swap1][risk.DollarPrice] is not None
        assert result[orig_swap1][risk.DollarPrice] is not None

        # Now reset the instruments and portfolio

        swap1 = IRSwap('Pay', '10y', 'USD', name='swap1')
        swap2 = IRSwap('Pay', '10y', 'GBP', name='swap2')
        swap3 = IRSwap('Pay', '10y', 'EUR', name='swap3')

        portfolio = Portfolio((swap1, swap2, swap3, swap1))

        with PricingContext(dt.date(2020, 10, 14)):
            # Resolve under a different pricing date
            portfolio.resolve()

        assert portfolio.instruments[0].termination_date == dt.date(
            2030, 10, 16)
        assert portfolio.instruments[1].termination_date == dt.date(
            2030, 10, 14)
        assert round(swap1.fixed_rate, 4) == 0.0075
        assert round(swap2.fixed_rate, 4) == 0.004
        assert round(swap3.fixed_rate, 4) == -0.0027

        # Assert that after resolution under a different context, we cannot retrieve the result

        try:
            _ = result[swap1][risk.DollarPrice]
            assert False
        except KeyError:
            assert True

        # Resolve again and check we get the same values

        with PricingContext(dt.date(2020, 10, 14)):
            # Resolve under a different pricing date
            portfolio.resolve()

        assert portfolio.instruments[0].termination_date == dt.date(
            2030, 10, 16)
        assert portfolio.instruments[1].termination_date == dt.date(
            2030, 10, 14)
        assert round(swap1.fixed_rate, 4) == 0.0075
        assert round(swap2.fixed_rate, 4) == 0.004
        assert round(swap3.fixed_rate, 4) == -0.0027
예제 #30
0
def test_adding_risk_results(mocker):
    with MockCalc(mocker):
        result1 = get_attributes(eur_port, risk.Price, no_frame=True)
        result2 = get_attributes(
            eur_port, (risk.IRDelta(aggregation_level=AggregationLevel.Asset,
                                    currency='local'), risk.Price),
            no_frame=True)
        result3 = get_attributes(
            swaption_port,
            (risk.IRDelta(aggregation_level=AggregationLevel.Asset,
                          currency='local'), risk.Price),
            no_frame=True)
        result4 = get_attributes(port1, risk.Price, no_frame=True)
        result5 = get_attributes(
            swaption_port,
            risk.IRVega(aggregation_level=AggregationLevel.Asset, ),
            no_frame=True)
        result6 = get_attributes(jpy_port, (risk.Price, ),
                                 'RollFwd',
                                 no_frame=True)
        result7 = get_attributes(jpy_port,
                                 risk.Price,
                                 'CurveScen1',
                                 no_frame=True)
        result8 = get_attributes(jpy_port, (risk.DollarPrice, risk.Price),
                                 'CurveScen2',
                                 no_frame=True)

        # (2020, 1, 14) to (2020, 1, 15)
        result9 = get_attributes(port1, risk.Price, 'Multiple', no_frame=True)
        # (2020, 1, 16) to (2020, 1, 17)
        result10 = get_attributes(port1,
                                  risk.Price,
                                  'Multiple2',
                                  no_frame=True)
        # (2020, 1, 14)
        result11 = get_attributes(port1, risk.Price, no_frame=True)
        # (2020, 1, 16), market_data_location='NYC'
        result12 = get_attributes(port1,
                                  risk.Price,
                                  'PricingCtx2',
                                  no_frame=True)
        # (2020, 1, 16), market_data_location='LDN'
        result13 = get_attributes(port1,
                                  risk.Price,
                                  'PricingCtx3',
                                  no_frame=True)

    # adding results with same portfolio but different risk measures
    add_1 = result3 + result5
    # adding results with different portfolio but same risk measures
    add_2 = result2 + result3
    # adding results with different portfolios and overlapping risk measures
    add_3 = result1 + result3
    # adding results with different portfolios and different risk measures
    add_4 = result1 + result5
    add_5 = result3 + result4

    # adding dates

    add_6 = result9 + result13
    add_7 = result11 + result13
    add_8 = result10 + result11
    add_9 = result9 + result10

    default_pivot_table_test(add_1, 'has_bucketed')
    default_pivot_table_test(add_2, 'has_bucketed')
    default_pivot_table_test(add_3, 'has_bucketed')
    default_pivot_table_test(add_4, 'has_bucketed')
    default_pivot_table_test(add_5, 'has_bucketed')
    default_pivot_table_test(add_6, 'dated')
    default_pivot_table_test(add_7, 'dated')
    default_pivot_table_test(add_8, 'dated')
    default_pivot_table_test(add_9, 'dated')

    # throw value error when adding results where at least one particular value is being calculated twice

    # adding results with same portfolio but overlapping risk measures
    with pytest.raises(ValueError):
        _ = result1 + result2

    # adding results with overlapping portfolios and different risk measures
    with pytest.raises(ValueError):
        _ = result2 + result4

    # adding results with overlapping portfolios and same risk measures
    with pytest.raises(ValueError):
        _ = result1 + result4

    # adding results with different scenarios
    with pytest.raises(ValueError):
        _ = result6 + result7
    with pytest.raises(ValueError):
        _ = result7 + result8

    # overlapping dates
    with pytest.raises(ValueError):
        _ = result9 + result11
    with pytest.raises(ValueError):
        _ = result10 + result13

    # adding results with different market locations
    with pytest.raises(ValueError):
        _ = result10 + result12
    with pytest.raises(ValueError):
        _ = result9 + result12
    with pytest.raises(ValueError):
        _ = result12 + result13
    with pytest.raises(ValueError):
        _ = result11 + result12