Esempio n. 1
0
def test_cache_addition_removal():
    # Don't use a mocker here as it will hold refs to things and break the cache removal test
    set_session()

    p1 = IRSwap('Pay', '10y', 'DKK')

    with PricingContext(use_cache=True):
        market_data_location = PricingContext.current.market_data_location
        pricing_date = PricingContext.current.pricing_date
        p1.price()

    assert PricingCache.get(p1, market_data_location, risk.Price, pricing_date)

    assert not PricingCache.get(p1, market_data_location, risk.IRDelta,
                                pricing_date)

    # Assert that deleting the cached instrument removes it from the PricingCache
    # N.B, this may not work when debugging tests
    del p1
    p2 = IRSwap('Pay', '10y', 'DKK')
    assert not PricingCache.get(p2, market_data_location, risk.Price,
                                pricing_date)

    with PricingContext(use_cache=True):
        p2.price()

    assert PricingCache.get(p2, market_data_location, risk.Price, pricing_date)

    # Change a property and assert that p2 is no longer cached
    p2.notional_currency = 'EUR'
    assert not PricingCache.get(p2, market_data_location, risk.Price,
                                pricing_date)
Esempio n. 2
0
    def _raise_order(
        self,
        state: Union[date, Iterable[date]],
        trigger_info: Optional[Union[AddTradeActionInfo,
                                     Iterable[AddTradeActionInfo]]] = None):
        with PricingContext(is_batch=True, show_progress=True):
            state_list = make_list(state)
            orders = {}
            if trigger_info is None or isinstance(trigger_info,
                                                  AddTradeActionInfo):
                trigger_info = [trigger_info for _ in range(len(state_list))]
            for s, ti in zip_longest(state_list, trigger_info):
                active_portfolio = self.action.dated_priceables.get(
                    s) or self.action.priceables
                with PricingContext(pricing_date=s):
                    orders[s] = (Portfolio(active_portfolio).resolve(
                        in_place=False), ti)
        final_orders = {}
        for d, p in orders.items():
            new_port = []
            for t in p[0].result():
                t.name = f'{t.name}_{d}'
                new_port.append(t)
            new_port = Portfolio(new_port)
            final_orders[d] = new_port.scale(
                None if p[1] is None else p[1].scaling, in_place=False)

        return final_orders
Esempio n. 3
0
def test_cache_subset(mocker):
    set_session()

    ir_swap = IRSwap('Pay', '10y', 'DKK')

    values = [
        {'date': '2019-10-07', 'value': 0.01},
        {'date': '2019-10-08', 'value': 0.01}
    ]
    mocker.return_value = [[values]]

    dates = (dt.date(2019, 10, 7), dt.date(2019, 10, 8))
    with HistoricalPricingContext(dates=dates, use_cache=True) as hpc:
        pricing_key = hpc.pricing_key
        price_f = ir_swap.price()
    price_f.result()

    cached = PricingCache.get(ir_swap, risk.Price, pricing_key)
    assert len(cached) == len(dates)

    cached_scalar = PricingCache.get(ir_swap, risk.Price, PricingContext(pricing_date=dates[0]).pricing_key)
    assert isinstance(cached_scalar, float)

    dates = dates + (dt.date(2019, 10, 9),)
    pricing_key = HistoricalPricingContext(dates=dates).pricing_key
    cached2 = PricingCache.get(ir_swap, risk.Price, pricing_key)
    assert cached2 is None

    cached3 = PricingCache.get(ir_swap, risk.Price, pricing_key, return_partial=True)
    assert len(cached3) < len(dates)

    values = [
        {'date': '2019-10-07', 'marketDataType': 'IR', 'assetId': 'USD', 'pointClass': 'Swap',
         'point': '1y', 'value': 0.01},
        {'date': '2019-10-07', 'marketDataType': 'IR', 'assetId': 'USD', 'pointClass': 'Swap',
         'point': '2y', 'value': 0.015},
        {'date': '2019-10-08', 'marketDataType': 'IR', 'assetId': 'USD', 'pointClass': 'Swap',
         'point': '1y', 'value': 0.01},
        {'date': '2019-10-08', 'marketDataType': 'IR', 'assetId': 'USD', 'pointClass': 'Swap',
         'point': '2y', 'value': 0.015},
        {'date': '2019-10-09', 'marketDataType': 'IR', 'assetId': 'USD', 'pointClass': 'Swap',
         'point': '1y', 'value': 0.01},
        {'date': '2019-10-09', 'marketDataType': 'IR', 'assetId': 'USD', 'pointClass': 'Swap',
         'point': '2y', 'value': 0.015}
    ]
    mocker.return_value = [[values]]

    with HistoricalPricingContext(dates=dates, use_cache=True) as hpc:
        pricing_key = hpc.pricing_key
        risk_f = ir_swap.calc(risk.IRDelta)

    risk_frame = risk_f.result()

    assert isinstance(risk_frame, pd.DataFrame)
    assert len(risk_frame.index.unique()) == len(dates)
    cached4 = PricingCache.get(ir_swap, risk.IRDelta, pricing_key)
    assert len(cached4.index.unique()) == len(dates)

    cached5 = PricingCache.get(ir_swap, risk.IRDelta, PricingContext(pricing_date=dates[0]).pricing_key)
    assert len(cached5.index.unique()) == len(cached5)
Esempio n. 4
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)
def test_pricing_dates():
    # May be on weekend but doesn't matter for basic test
    future_date = dt.date.today() + dt.timedelta(2)
    yesterday = dt.date.today() - dt.timedelta(1)
    pc = PricingContext(pricing_date=future_date, market=CloseMarket(yesterday))
    assert pc is not None
    with pytest.raises(ValueError, match="pricing_date in the future"):
        PricingContext(pricing_date=future_date)
Esempio n. 6
0
    def run_backtest(cls, strategy, start=None, end=None, frequency='BM', window=None, states=None, risks=Price,
                     show_progress=True):
        dates = pd.date_range(start=start, end=end, freq=frequency).date.tolist()
        risks = make_list(risks) + strategy.risks

        backtest = BackTest(strategy, dates, risks)

        if strategy.initial_portfolio is not None:
            for date in dates:
                backtest.portfolio_dict[date].append(strategy.initial_portfolio)

        for trigger in strategy.triggers:
            if trigger.calc_type != CalcType.path_dependent:
                triggered_dates = [date for date in dates if trigger.has_triggered(date, backtest)]
                for action in trigger.actions:
                    if action.calc_type != CalcType.path_dependent:
                        action.apply_action(triggered_dates, backtest)

        with PricingContext(is_batch=True, show_progress=show_progress):
            for day, portfolio in backtest.portfolio_dict.items():
                with PricingContext(day):
                    backtest.calc_calls += 1
                    backtest.calculations += len(portfolio) * len(risks)
                    backtest.add_results(day, portfolio.calc(tuple(risks)))

            # semi path dependent initial calc
            for _, scaling_list in backtest.scaling_portfolios.items():
                for p in scaling_list:
                    with HistoricalPricingContext(dates=p.dates):
                        backtest.calc_calls += 1
                        backtest.calculations += len(p.dates) * len(risks)
                        p.results = Portfolio([p.trade]).calc(tuple(risks))

        for date in dates:
            # semi path dependent scaling
            if date in backtest.scaling_portfolios:
                for p in backtest.scaling_portfolios[date]:
                    scale_date = p.dates[0]
                    scaling_factor = backtest.results[scale_date][p.risk][0] / p.results[scale_date][p.risk][0]
                    scaled_trade = p.trade.as_dict()
                    scaled_trade['notional_amount'] *= -scaling_factor
                    scaled_trade = Instrument.from_dict(scaled_trade)
                    for day in p.dates:
                        backtest.add_results(day, p.results[day] * -scaling_factor)
                        backtest.portfolio_dict[day] += Portfolio(scaled_trade)

            # path dependent
            for trigger in strategy.triggers:
                if trigger.calc_type == CalcType.path_dependent:
                    if trigger.has_triggered(date, backtest):
                        for action in trigger.actions:
                            action.apply_action(date, backtest)
                else:
                    for action in trigger.actions:
                        if action.calc_type == CalcType.path_dependent:
                            if trigger.has_triggered(date, backtest):
                                action.apply_action(date, backtest)
            return backtest
Esempio n. 7
0
 def _raise_order(self, state: Union[date, Iterable[date]]):
     with PricingContext(is_batch=True):
         orders = {}
         for s in state:
             active_portfolio = self.action.dated_priceables.get(
                 s) or self.action.priceables
             with PricingContext(pricing_date=s):
                 orders[s] = Portfolio(active_portfolio).resolve(
                     in_place=False)
     return orders
Esempio n. 8
0
def test_cache_subset(mocker):
    set_session()

    ir_swap = IRSwap('Pay', '10y', 'DKK')

    values = [{'$type': 'Risk', 'val': 0.01}]
    mocker.return_value = [[[values]], [[values]]]

    dates = (dt.date(2019, 10, 7), dt.date(2019, 10, 8))
    with HistoricalPricingContext(dates=dates, use_cache=True):
        price_f = ir_swap.price()
    price_f.result()

    for date in dates:
        risk_key = PricingContext(pricing_date=date)._PricingContext__risk_key(
            risk.Price, ir_swap.provider)
        cached_scalar = PricingCache.get(risk_key, ir_swap)
        assert cached_scalar
        assert isinstance(cached_scalar, float)

    risk_key = PricingContext(
        pricing_date=dt.date(2019, 10, 9))._PricingContext__risk_key(
            risk.Price, ir_swap.provider)
    cached2 = PricingCache.get(risk_key, ir_swap)
    assert cached2 is None

    values = [{
        '$type':
        'RiskVector',
        'asset': [0.01, 0.015],
        'points': [{
            'type': 'IR',
            'asset': 'USD',
            'class_': 'Swap',
            'point': '1y'
        }, {
            'type': 'IR',
            'asset': 'USD',
            'class_': 'Swap',
            'point': '2y'
        }]
    }]

    # Check that we can return the same values from the cache, after calculating once (with return values set to None)

    for return_values in ([[[values]], [[values]], [[values]]], None):
        mocker.return_value = return_values

        with HistoricalPricingContext(dates=dates, use_cache=True):
            risk_f = ir_swap.calc(risk.IRDelta)

        risk_frame = risk_f.result()

        assert isinstance(risk_frame, pd.DataFrame)
        assert len(risk_frame.index.unique()) == len(dates)
Esempio n. 9
0
def test_multiple_measures(mocker):
    day = [
        [
            [{
                '$type': 'RiskVector',
                'asset': [0.01, 0.015],
                'points': [
                    {'type': 'IR Vol', 'asset': 'USD-LIBOR-BBA', 'class_': 'Swap', 'point': '1y'},
                    {'type': 'IR Vol', 'asset': 'USD-LIBOR-BBA', 'class_': 'Swap', 'point': '2y'}
                ]
            }]
        ],
        [
            [{
                '$type': 'RiskVector',
                'asset': [0.01, 0.015],
                'points': [
                    {'type': 'IR', 'asset': 'USD', 'class_': 'Swap', 'point': '1y'},
                    {'type': 'IR', 'asset': 'USD', 'class_': 'Swap', 'point': '2y'}
                ]
            }],
        ],
        [
            [{'$type': 'Risk', 'val': 0.01}]
        ]
    ]

    mocker.return_value = [day, day, day]

    set_session()

    ir_swaption = IRSwaption('Pay', '10y', 'USD')

    dates = (dt.date(2019, 10, 7), dt.date(2019, 10, 8), dt.date(2019, 10, 9))
    with HistoricalPricingContext(dates=dates, use_cache=True):
        ir_swaption.price()
        ir_swaption.calc(risk.IRDelta)
        ir_swaption.calc(risk.IRVega)

    # make sure all the risk measures got cached correctly
    for date in dates:
        with PricingContext(pricing_date=date) as pc:
            for risk_measure in (risk.Price, risk.IRDelta, risk.IRVega):
                val = PricingCache.get(pc._PricingContext__risk_key(risk_measure, ir_swaption.provider), ir_swaption)
                assert val is not None

    with PricingContext(pricing_date=dt.date(2019, 10, 11)) as pc:
        for risk_measure in (risk.Price, risk.IRDelta, risk.IRVega):
            val = PricingCache.get(pc._PricingContext__risk_key(risk_measure, ir_swaption.provider), ir_swaption)
            assert val is None
Esempio n. 10
0
 def _raise_order(self,
                  state: Union[date, Iterable[date]],
                  trigger_info: Optional[Union[AddTradeActionInfo, Iterable[AddTradeActionInfo]]] = None):
     with PricingContext(is_batch=True):
         state_list = make_list(state)
         orders = {}
         if trigger_info is None or isinstance(trigger_info, AddTradeActionInfo):
             trigger_info = [trigger_info for _ in range(len(state_list))]
         for s, ti in zip_longest(state_list, trigger_info):
             active_portfolio = self.action.dated_priceables.get(s) or self.action.priceables
             with PricingContext(pricing_date=s):
                 orders[s] = (Portfolio(active_portfolio).resolve(in_place=False), ti)
     orders = {k: v[0].result().scale(None if v[1] is None else v[1].scaling, in_place=False) for k, v in
               orders.items()}
     return orders
Esempio n. 11
0
    def run_backtest(cls,
                     strategy,
                     start=None,
                     end=None,
                     frequency='BM',
                     window=None,
                     states=None,
                     risks=Price,
                     show_progress=True):
        dates = pd.date_range(start=start, end=end,
                              freq=frequency).date.tolist()
        risks = make_list(risks) + strategy.risks

        backtest = BackTest(strategy, dates, risks)

        for trigger in strategy.triggers:
            if trigger.deterministic:
                triggered_dates = [
                    date for date in dates
                    if trigger.has_triggered(date, backtest)
                ]
                for action in trigger.actions:
                    if action.deterministic:
                        action.apply_action(triggered_dates, backtest)

        with PricingContext(is_batch=True, show_progress=show_progress):
            for day, portfolio in backtest.portfolio_dict.items():
                with PricingContext(day):
                    backtest.calc_calls += 1
                    backtest.calculations += len(portfolio) * len(risks)
                    backtest.add_results(
                        day,
                        portfolio.calc(risks[0] if len(risks) ==
                                       1 else tuple(risks)))

        for trigger in strategy.triggers:
            if not trigger.deterministic:
                for date in dates:
                    if trigger.has_triggered(date, backtest):
                        for action in trigger.actions:
                            action.apply_action(date, backtest)
            else:
                for action in trigger.actions:
                    if not action.deterministic:
                        for date in dates:
                            if trigger.has_triggered(date, backtest):
                                action.apply_action(date, backtest)
        return backtest
Esempio n. 12
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)
Esempio n. 13
0
def get_risk_request_id(requests):
    """
    This is not a formal equality of the risk request as it covers only the names of core components.  When a formal
    eq function is provided on risk_request then this should be replaced with something derived from that.
    :param requests: a collection of RiskRequests
    :type requests: tuple of RiskRequest
    :return: hash
    :rtype: str
    """
    identifier = str(len(requests))
    for request in requests:
        identifier += '_'
        identifier += '-'.join([pos.instrument.name for pos in request.positions])
        identifier += '-'.join([str(risk) for risk in request.measures])
        date = request.pricing_and_market_data_as_of[0].pricing_date.strftime('%Y%b%d')
        today = PricingContext().pricing_date.strftime('%Y%b%d')
        identifier += 'today' if date == today else date
        if request.scenario is not None:
            scenario_identifier = []
            for k, v in request.scenario.scenario.as_dict().items():
                if k != 'shocks':
                    scenario_identifier.append(str(k) + "=" + str(v))
                else:
                    shock_value = 'shock_value' + "=" + str(v[0].shock.value)
                    pattern = v[0].pattern
                    shock_pattern = 'shock_pattern' + "=" + '-'.join(
                        [str(m) for m in [pattern.mkt_type, pattern.mkt_asset, pattern.mkt_class]])
                    scenario_identifier.append(shock_value + "+" + shock_pattern)
            identifier += '+'.join(sorted(scenario_identifier))
    return hashlib.md5(identifier.encode('utf-8')).hexdigest()
Esempio n. 14
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)
    def process(self):
        a_data = self.children_data.get('a')
        if isinstance(a_data, ProcessorResult):
            if a_data.success:
                date_array = a_data.data.reset_index()['date']
                if self.end is None:
                    self.end = max(date_array)
                if self.start is None:
                    self.start = min(date_array)
                if not isinstance(self.weekdays_only, bool):
                    self.value = ProcessorResult(
                        False,
                        "DateRangeProcessor requires weekdays_only argument to be a boolean."
                    )
                yesterday = date.today() - timedelta(days=1)
                with PricingContext(pricing_date=yesterday):
                    # for EOD datasets latest datapoint is T-1,
                    # relative dates will be evaluated using yesterday as base_date
                    if isinstance(self.end, RelativeDate):
                        self.end = self.end.apply_rule()
                    if isinstance(self.start, RelativeDate):
                        self.start = self.start.apply_rule()

                result = date_range(a_data.data,
                                    start_date=self.start,
                                    end_date=self.end,
                                    weekdays_only=self.weekdays_only)
                self.value = ProcessorResult(True, result)
            else:
                self.value = ProcessorResult(
                    False,
                    "DateRangeProcessor does not have 'a' series values yet")
        else:
            self.value = ProcessorResult(
                False, "DateRangeProcessor does not have 'a' series yet")
Esempio n. 16
0
    def apply_action(self, state: Union[datetime.date, Iterable[datetime.date]], backtest: BackTest):
        with PricingContext(is_batch=True):
            f = {}
            for s in state:
                active_portfolio = self._dated_priceables.get(s) or self._priceables
                with PricingContext(pricing_date=s):
                    f[s] = Portfolio(active_portfolio).resolve(in_place=False)

        for s in backtest.states:
            pos = []
            for create_date, portfolio in f.items():
                pos += [inst for inst in portfolio.result().instruments
                        if get_final_date(inst, create_date, self.trade_duration) >= s >= create_date]
            backtest.portfolio_dict[s].append(pos)

        return backtest
Esempio n. 17
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
Esempio n. 18
0
def test_structured_calc(mocker):
    set_session()

    for priceable in priceables:
        if priceable.assetClass == AssetClass.Rates:
            for measure in (risk.IRDelta, risk.IRVega):
                structured_calc(mocker, priceable, measure)
        elif priceable.assetClass == AssetClass.FX:
            for measure in (risk.FXDelta, risk.FXGamma, risk.FXVega):
                structured_calc(mocker, priceable, measure)

    values = {
        '$type': 'RiskVector',
        'asset': [0.01, 0.015],
        'points': [
            {'type': 'IR', 'asset': 'USD', 'class_': 'Swap', 'point': '1y'},
            {'type': 'IR', 'asset': 'USD', 'class_': 'Swap', 'point': '2y'}
        ]
    }

    mocker.return_value = [[[[values]] * len(priceables)]]

    with PricingContext():
        delta_f = [p.calc(risk.IRDelta) for p in priceables]

    delta = risk.aggregate_risk(delta_f, threshold=0)

    assert len(delta) == 2
Esempio n. 19
0
def test_structured_calc(mocker):
    set_session()

    for priceable in priceables:
        if priceable.assetClass == AssetClass.Rates:
            for measure in (risk.IRDelta, risk.IRVega):
                structured_calc(mocker, priceable, measure)
        elif priceable.assetClass == AssetClass.FX:
            for measure in (risk.FXDelta, risk.FXGamma, risk.FXVega):
                structured_calc(mocker, priceable, measure)

    values = [{
        'marketDataType': 'IR',
        'assetId': 'USD',
        'pointClass': 'Swap',
        'point': '1y',
        'value': 0.01
    }, {
        'marketDataType': 'IR',
        'assetId': 'USD',
        'pointClass': 'Swap',
        'point': '2y',
        'value': 0.015
    }]

    mocker.return_value = [[values] * len(priceables)]

    with PricingContext():
        delta_f = [p.calc(risk.IRDelta) for p in priceables]

    delta = risk.aggregate_risk(delta_f, threshold=0)

    assert len(delta) == 2
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)
Esempio n. 21
0
def test_async_calc(mocker):
    set_session()

    mocker.return_value = [[[[{'$type': 'Risk', 'val': 0.01 * idx}] for idx in range(len(priceables))]]]

    with PricingContext():
        dollar_price_f = [p.dollar_price() for p in priceables]

    prices = tuple(f.result() for f in dollar_price_f)
    assert prices == tuple(0.01 * i for i in range(len(priceables)))
Esempio n. 22
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
Esempio n. 23
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
Esempio n. 24
0
def get_attributes(p, risks, ctx='PricingCtx1', resolve=False, no_frame=False):
    if resolve:
        p.resolve()
    if ctx == 'Multiple':
        with HistoricalPricingContext(date(2020, 1, 14),
                                      date(2020, 1, 15),
                                      market_data_location='LDN'):
            res = p.calc(risks)
    elif ctx == 'PricingCtx1':
        with PricingContext(date(2020, 1, 14), market_data_location='LDN'):
            res = p.calc(risks)
    elif ctx == 'Multiple2':
        with HistoricalPricingContext(date(2020, 1, 16),
                                      date(2020, 1, 17),
                                      market_data_location='LDN'):
            res = p.calc(risks)
    elif ctx == 'PricingCtx2':
        with PricingContext(date(2020, 1, 16), market_data_location='NYC'):
            res = p.calc(risks)
    elif ctx == 'PricingCtx3':
        with PricingContext(date(2020, 1, 16), market_data_location='LDN'):
            res = p.calc(risks)
    elif ctx == 'RollFwd':
        with RollFwd(date=date(2020, 11, 3)):
            res = p.calc(risks)
    elif ctx == 'CurveScen1':
        with CurveScenario(parallel_shift=5):
            res = p.calc(risks)
    elif ctx == 'CurveScen2':
        with CurveScenario(curve_shift=1, tenor_start=5, tenor_end=30):
            res = p.calc(risks)

    if not no_frame:
        frame = res.to_frame(None, None, None)

        cols = [col for col in frame.columns]
        return cols, res, frame
    else:
        return res
Esempio n. 25
0
def test_disjoint_priceables_measures(mocker):
    set_session()

    swap = priceables[4]
    swaption = priceables[6]

    mocker.return_value = [[[[{'$type': 'Risk', 'val': 0.01}]]]] * 2

    with PricingContext():
        swap_price_f = swap.price()
        swaption_dollar_price_f = swaption.dollar_price()

    assert swap_price_f.result() == 0.01
    assert swaption_dollar_price_f.result() == 0.01
Esempio n. 26
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
Esempio n. 27
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
Esempio n. 28
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
Esempio n. 29
0
    def apply_action(self, state: datetime.date, backtest: BackTest):
        with PricingContext(pricing_date=state):
            f = self._priceable.resolve(in_place=False)
            hedge_delta = self._priceable.calc(self.risk)

        hedge = f.result()
        ratio = backtest.results[state][self.risk].aggregate() / hedge_delta.result()
        hedge = scale_trade(hedge, ratio)

        active_dates = [pricing_date for pricing_date in backtest.states if
                        get_final_date(hedge, state, self.trade_duration) >= pricing_date >= state]
        with HistoricalPricingContext(dates=active_dates):
            backtest.calc_calls += 1
            backtest.calculations += len(active_dates) * len(backtest.risks)
            hedge_res = Portfolio(hedge).calc(backtest.risks)

        for pricing_date in active_dates:
            results = hedge_res[pricing_date]
            backtest.add_results(pricing_date, results)
Esempio n. 30
0
def get_risk_request_id(requests):
    """
    This is not a formal equality of the risk request as it covers only the names of core components.  When a formal
    eq function is provided on risk_request then this should be replaced with something derived from that.
    :param requests: a collection of RiskRequests
    :type requests: tuple of RiskRequest
    :return: hash
    :rtype: str
    """
    identifier = str(len(requests))
    for request in requests:
        identifier += '_'
        identifier += '-'.join([pos.instrument.name for pos in request.positions])
        identifier += '-'.join([str(risk) for risk in request.measures])
        date = request.pricing_and_market_data_as_of[0].pricing_date.strftime('%Y%b%d')
        today = PricingContext().pricing_date.strftime('%Y%b%d')
        identifier += 'today' if date == today else date
        identifier += '+'.join(sorted(str(k) + "=" + str(v) for k, v in request.scenario.scenario.as_dict().items())) \
            if request.scenario is not None else ''
    return identifier[:232]  # cut down to less than max number of char for filename