def test_should_have_more_units_than_buy_order_size_when_have_short_current_position_and_order_breaches_default_limit(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-100000) self.assign_unity_rates(rm) rm.append_position('CHF', -10) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, rm.ccy_limit+10)
def test_should_not_filter_order_without_rates(self): rmo = CcyExposureLimitRiskEvaluator('ABC', FxPricesCache()) try: rmo.filter_order(OrderEvent('CHF_USD', 1000, 'buy')) self.fail('Filtered order without fx rates') except AssertionError: pass
def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy(self): ccy_limits_short = {'CHF': -234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits_short=ccy_limits_short) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 100, 'sell') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 100)
def test_should_allow_to_set_unity_fx_rate_and_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy(self): ccy_limits = {'CHF': 110} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits) rm.rates_cache.set_rate(TickEvent('CHF_SGD', get_time(), 1.0, 1.0)) order = OrderEvent('CHF_SGD', 150, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 110)
def test_should_allow_to_set_short_ccy_limit_and_unset_long_limit(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.set_limit('SHF_USD', ccy_limit=10000) self.assertEquals(rm.ccy_limits['SHF_USD'], 10000) rm.set_limit('SHF_USD', ccy_limit_short=-22) self.assertEquals(rm.ccy_limits_short['SHF_USD'], -22) self.assertFalse('SHF_USD' in rm.ccy_limits)
def test_filtered_order_should_have_less_units_when_order_size_breaches_non_default_short_ccy_limit_on_2nd_ccy(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-150, ccy_limits={'EUR': 10000}) self.assign_unity_rates(rm) order = OrderEvent('EUR_SGD', 10000, 'buy') filtered = rm.filter_order(order) self.assertNotEquals(filtered.units, 10000) self.assertEquals(abs(rm.ccy_limit_short), filtered.units)
def test_filtered_order_should_have_less_units_when_order_size_breaches_both_specific_and_default_limit_on_1st_ccy(self): ccy_limits = {'CHF': 12000} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits, ccy_limit_short=-100000) self.assign_unity_rates(rm) order = OrderEvent('CHF_SGD', 15000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 12000)
def test_should_allow_to_set_unity_fx_rate_and_have_same_units(self): ccy_limits = {'CHF': 110} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits) rm.rates_cache.set_rate(TickEvent('CHF_SGD', get_time(), 1.0, 1.0)) order = OrderEvent('CHF_SGD', 105, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 105)
def test_filtered_order_should_have_same_units_when_order_size_plus_current_position_does_not_breach_default_limit(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache) self.assign_unity_rates(rm) rm.append_position('CHF', 10) order = OrderEvent('CHF_USD', 100, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 100)
def test_filtered_order_should_have_less_units_when_order_size_plus_current_position_breaches_specific_limit(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limits={'CHF': 1234}) self.assign_unity_rates(rm) rm.append_position('CHF', 10) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, rm.ccy_limits['CHF']-10)
def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_short_limit_on_2nd_ccy_with_fx_rate_greater_than_1(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limits_short={'EUR': -100}) self.assign_dummy_rates(rm) order = OrderEvent('SGD_EUR', 2000, 'buy') filtered = rm.filter_order(order) amount_in_base_ccy = round(-1 * rm.ccy_limits_short['EUR'] / rm.rates_cache.get_rate('EUR_USD')['bid'], 0) self.assertEquals(amount_in_base_ccy, filtered.units)
def test_should_not_filter_order_without_rates(self): rmo = CcyExposureLimitRiskEvaluator('ABC', FxPricesCache()) try: rmo.filter_order(OrderEvent('CHF_USD', 1000, 'buy')) self.fail('Filtered order without fx rates') except AssertionError: pass
def test_filtered_order_should_have_less_units_when_order_size_does_not_breach_specific_limit_more_than_default_on_1st_ccy_with_fx_rate_gt_1(self): ccy_limits = {'CHF': 10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=1000, ccy_limits=ccy_limits, ccy_limit_short=-10000) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) amount_in_base_ccy = round(rm.ccy_limits['CHF'] / rm.rates_cache.get_rate('CHF_USD')['ask'], 0) self.assertEquals(amount_in_base_ccy, filtered.units)
def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy(self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', ccy_limit=100, ccy_limits=ccy_limits) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') amount_in_base_ccy = round(rm.ccy_limits['CHF'] / self.rm.rates.get_rate('CHF_USD')['ask'], 0) filtered = rm.filter_order(order) self.assertEquals(amount_in_base_ccy, filtered.units)
def test_filtered_sell_order_should_have_same_units_when_order_size_breaches_short_specific_limit_more_than_default_short_limit_on_1st_ccy(self): ccy_limits_short = {'CHF': -10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-1000, ccy_limits_short=ccy_limits_short, ccy_limit=100000) self.assign_unity_rates(rm) order = OrderEvent('CHF_USD', 10000, 'sell') filtered = rm.filter_order(order) self.assertEquals(10000, filtered.units) self.assertEquals(filtered.instrument, 'CHF_USD') self.assertEquals(filtered.side, 'sell')
def test_should_allow_to_set_unity_fx_rate_and_have_same_units(self): ccy_limits = {'CHF': 110} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits) rm.rates_cache.set_rate(TickEvent('CHF_SGD', get_time(), 1.0, 1.0)) order = OrderEvent('CHF_SGD', 105, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 105)
def test_filtered_order_should_have_same_units_when_order_size_equals_non_default_short_ccy_limit_on_2nd_ccy( self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limits_short={'USD': -1000}, ccy_limits={'CHF': 1500}) self.assign_unity_rates(rm) order = OrderEvent('CHF_USD', 1000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 1000)
def test_filtered_sell_order_should_have_less_units_when_order_size_breaches_short_specific_limit_less_than_default_short_limit_on_1st_ccy(self): ccy_limits_short = {'CHF': -100} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-1000, ccy_limits_short=ccy_limits_short) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 1000, 'sell') amount_in_base_ccy = round(-1 * rm.ccy_limits_short['CHF'] / self.rm.rates_cache.get_rate('CHF_USD')['bid'], 0) filtered = rm.filter_order(order) self.assertEquals(amount_in_base_ccy, filtered.units) self.assertEquals(filtered.instrument, 'CHF_USD') self.assertEquals(filtered.side, 'sell')
def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_short_ccy_limit_on_2nd_ccy( self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limits_short={'USD': -1000}, ccy_limits={'CHF': 15000}) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) self.assertEquals(1000, filtered.units)
def test_filtered_sell_order_should_have_same_units_when_order_size_does_not_breach_specific_short_limit_on_2nd_ccy_and_size_equals_default_limit_on_1sr_ccy( self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits_short={'CHF': -234}) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 100, 'sell') filtered = rm.filter_order(order) self.assertEquals(100, filtered.units)
def test_should_allow_to_set_unity_fx_rate_and_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy( self): ccy_limits = {'CHF': 110} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits) rm.rates_cache.set_rate(TickEvent('CHF_SGD', get_time(), 1.0, 1.0)) order = OrderEvent('CHF_SGD', 150, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 110)
def test_filtered_order_should_have_less_units_when_order_size_breaches_non_default_short_ccy_limit_on_2nd_ccy( self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-150, ccy_limits={'EUR': 10000}) self.assign_unity_rates(rm) order = OrderEvent('EUR_SGD', 10000, 'buy') filtered = rm.filter_order(order) self.assertNotEquals(filtered.units, 10000) self.assertEquals(abs(rm.ccy_limit_short), filtered.units)
def test_filtered_sell_order_should_have_less_units_when_order_size_breaches_specific_short_limit_on_2nd_ccy_with_fx_rate_greater_than_1( self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limits_short={'EUR': -100}) self.assign_dummy_rates(rm) order = OrderEvent('SGD_EUR', 5000, 'sell') filtered = rm.filter_order(order) amount_in_base_ccy = round( rm.ccy_limit / rm.rates_cache.get_rate('EUR_USD')['ask'], 0) self.assertEquals(amount_in_base_ccy, filtered.units)
def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy( self): ccy_limits_short = {'CHF': -234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits_short=ccy_limits_short) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 100, 'sell') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 100)
def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy( self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', ccy_limit=100, ccy_limits=ccy_limits) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') amount_in_base_ccy = round( rm.ccy_limits['CHF'] / self.rm.rates.get_rate('CHF_USD')['ask'], 0) filtered = rm.filter_order(order) self.assertEquals(amount_in_base_ccy, filtered.units)
def test_filtered_order_should_have_less_units_when_order_size_breaches_both_specific_and_default_limit_on_1st_ccy( self): ccy_limits = {'CHF': 12000} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits, ccy_limit_short=-100000) self.assign_unity_rates(rm) order = OrderEvent('CHF_SGD', 15000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 12000)
def test_filtered_sell_order_should_have_same_units_when_order_size_breaches_short_specific_limit_more_than_default_short_limit_on_1st_ccy( self): ccy_limits_short = {'CHF': -10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-1000, ccy_limits_short=ccy_limits_short, ccy_limit=100000) self.assign_unity_rates(rm) order = OrderEvent('CHF_USD', 10000, 'sell') filtered = rm.filter_order(order) self.assertEquals(10000, filtered.units) self.assertEquals(filtered.instrument, 'CHF_USD') self.assertEquals(filtered.side, 'sell')
def test_should_allow_second_instrument_without_breach_if_first_instrument_breaches_specific_limit(self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits) self.assign_unity_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) amount_in_base_ccy = round(rm.ccy_limits['CHF'] / rm.rates_cache.get_rate('CHF_USD')['ask']) self.assertEquals(filtered.units, amount_in_base_ccy) rm.append_position(filtered.instrument, filtered.units) order = OrderEvent('EUR_SGD', 1000, 'buy') filtered = rm.filter_order(order) self.assertNotEquals(filtered.units, 1000) self.assertEquals(filtered.units, 100)
def test_should_allow_specific_limit_on_second_instrument_with_current_position_on_first_complex(self): ccy_limits = {'CHF': 1234, 'EUR': 10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits, ccy_limit_short=-100000) self.assign_unity_rates(rm) rm.append_position('EUR', 100) filtered = rm.filter_order(OrderEvent('CHF_USD', 10000, 'buy')) self.assertEquals(filtered.units, 1234) rm.append_position('CHF', filtered.units) filtered = rm.filter_order(OrderEvent('EUR_USD', 5000, 'buy')) self.assertEquals(filtered.units, 5000) rm.append_position('EUR', filtered.units) filtered = rm.filter_order(OrderEvent('EUR_USD', 50000, 'buy')) self.assertEquals(filtered.units, 4900)
def test_filtered_order_should_have_less_units_when_order_size_does_not_breach_specific_limit_more_than_default_on_1st_ccy_with_fx_rate_gt_1( self): ccy_limits = {'CHF': 10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=1000, ccy_limits=ccy_limits, ccy_limit_short=-10000) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) amount_in_base_ccy = round( rm.ccy_limits['CHF'] / rm.rates_cache.get_rate('CHF_USD')['ask'], 0) self.assertEquals(amount_in_base_ccy, filtered.units)
def test_filtered_sell_order_should_have_less_units_when_order_size_breaches_short_specific_limit_less_than_default_short_limit_on_1st_ccy( self): ccy_limits_short = {'CHF': -100} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-1000, ccy_limits_short=ccy_limits_short) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 1000, 'sell') amount_in_base_ccy = round( -1 * rm.ccy_limits_short['CHF'] / self.rm.rates_cache.get_rate('CHF_USD')['bid'], 0) filtered = rm.filter_order(order) self.assertEquals(amount_in_base_ccy, filtered.units) self.assertEquals(filtered.instrument, 'CHF_USD') self.assertEquals(filtered.side, 'sell')
def test_should_not_allow_ccy_exposure_manager_of_different_base_ccy(self): try: portfolio = FxPortfolio('USD', 100) portfolio.set_ccy_exposure_manager( CcyExposureLimitRiskEvaluator('CHF', self.cache)) except ValueError: pass
def step_impl(context, base_ccy): context.pm = FxPortfolio(base_ccy, 10000) context.pm.set_price_cache(context.rates_cache) context.pm.set_ccy_exposure_manager( CcyExposureLimitRiskEvaluator(base_ccy, context.rates_cache, ccy_limit=5000))
def test_filtered_order_should_have_same_units_when_order_size_does_not_breach_non_default_limit_on_1st_ccy( self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=150) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 140, 'buy') filtered = self.rm.filter_order(order) self.assertEquals(filtered.units, 140)
def test_should_filters_two_orders_in_different_instruments_correctly3(self): ccy_limits = {'CHF': 1234, 'EUR': 10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits, ccy_limit_short=-100000) self.assign_unity_rates(rm) rm.append_position('EUR', -100) filtered = rm.filter_order(OrderEvent('CHF_USD', 10000, 'buy')) self.assertEquals(filtered.units, 1234) filtered = rm.filter_order(OrderEvent('EUR_USD', 5000, 'buy')) self.assertEquals(filtered.units, 5000) rm.append_position('EUR', filtered.units) filtered = rm.filter_order(OrderEvent('EUR_USD', 50000, 'buy')) self.assertEquals(filtered.units, 5100)
def test_should_allow_specific_limit_on_second_instrument_with_current_position_on_first(self): ccy_limits = {'CHF': 1234, 'EUR': 10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits) self.assign_unity_rates(rm) rm.append_position('EUR', 100) filtered = rm.filter_order(OrderEvent('CHF_USD', 10000, 'buy')) self.assertEquals(filtered.units, 1234) rm.append_position(filtered.instrument, filtered.units)
def test_should_allow_second_instrument_without_breach_if_first_instrument_breaches_specific_limit(self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits) self.assign_unity_rates(rm) rm.append_position('CHF', 10) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, rm.ccy_limits['CHF']-10) rm.append_position(filtered.instrument, filtered.units) order = OrderEvent('EUR_SGD', 100, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 100)
def test_should_allow_to_set_short_ccy_limit_and_unset_long_limit(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.set_limit('SHF_USD', ccy_limit=10000) self.assertEquals(rm.ccy_limits['SHF_USD'], 10000) rm.set_limit('SHF_USD', ccy_limit_short=-22) self.assertEquals(rm.ccy_limits_short['SHF_USD'], -22) self.assertFalse('SHF_USD' in rm.ccy_limits)
def setUp(self): self.portfolio = FxPortfolio('USD', 5000) self.cache = FxPricesCache() self.ccy_exposure_manager = \ CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=5000, ccy_limit_short=-5000) self.portfolio.set_price_cache(self.cache).set_ccy_exposure_manager( self.ccy_exposure_manager) self.large_buy_order = OrderEvent('EUR_USD', 1000000000, 'buy') self.large_sell_order = OrderEvent('EUR_USD', 1000000000, 'sell') self.buy_order = OrderEvent('EUR_USD', 1000, 'buy') self.sell_order = OrderEvent('EUR_USD', 1000, 'sell')
def setUp(self): self.portfolio = FxPortfolio('USD', 5000) self.cache = FxPricesCache() self.ccy_exposure_manager = CcyExposureLimitRiskEvaluator( 'USD', self.cache) self.portfolio.set_price_cache(self.cache) self.portfolio.set_ccy_exposure_manager(self.ccy_exposure_manager) self.buy_100_CHF_USD = OrderEvent('CHF_USD', 100, 'buy') self.sell_100_CHF_USD = OrderEvent('CHF_USD', 100, 'sell') self.buy_50_CHF_USD = OrderEvent('CHF_USD', 50, 'buy') self.sell_50_CHF_USD = OrderEvent('CHF_USD', 50, 'sell') self.buy_100_EUR_USD = OrderEvent('EUR_USD', 100, 'buy') self.sell_100_EUR_USD = OrderEvent('EUR_USD', 100, 'sell') self.buy_50_EUR_USD = OrderEvent('EUR_USD', 50, 'buy') self.sell_50_EUR_USD = OrderEvent('EUR_USD', 50, 'sell')
def wire(self, com_q=None, in_q=None, out_q=None, hb_q=None, e_q=None): portfolio = FxPortfolio(self.portfolio_ccy, self.portfolio_balance, port_limit=self.portfolio_limit, port_limit_short=self.portfolio_limit_short) ccy_exposure_manager = \ CcyExposureLimitRiskEvaluator(self.portfolio_ccy, self.prices_cache, ccy_limit=10000, ccy_limit_short=-10000) portfolio.set_price_cache( self.prices_cache).set_ccy_exposure_manager(ccy_exposure_manager) rm = FxPositionLimitRiskEvaluator(posLimit=10000, posLimitShort=-10000) portfolio.add_risk_manager(rm) portfolio_loop = EventLoop(in_q, portfolio, processed_event_q=out_q) portfolio_loop.set_command_q(com_q) return portfolio_loop
def test_should_allow_second_instrument_without_breach_if_another_instrument_already_breached(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache) self.assign_unity_rates(rm) rm.append_position('CHF', 10) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) self.assertNotEquals(filtered.units, 10000) self.assertEquals(filtered.units, rm.ccy_limit-10) order = OrderEvent('EUR_SGD', 100, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 100)
def test_should_filters_two_orders_in_different_instruments_correctly2(self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits) self.assign_unity_rates(rm) rm.append_position('CHF', -100) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 1334) order = OrderEvent('EUR_SGD', 1000, 'buy') filtered = rm.filter_order(order) self.assertNotEquals(filtered.units, 1000) self.assertEquals(filtered.units, 100)
def test_should_allow_short_current_position(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100) rm.append_position('CHF', -10)
def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_short_ccy_limit_on_2nd_ccy(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limits_short={'USD': -1000}, ccy_limits={'CHF': 15000}) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) self.assertEquals(1000, filtered.units)
def setUp(self): self.cache = FxPricesCache() self.rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-100000) self.assign_dummy_rates(self.rm)
def test_should_allow_to_set_short_ccy_limit_and_have_expected_value(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache, ccy_limits={}) rm.set_limit('CHF', ccy_limit_short=-1234.5) self.assertEquals(rm.ccy_limits_short['CHF'], -1234.5)
def test_should_allow_to_append_positions(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.append_position('EUR_CHF', 123)
def test_filtered_sell_order_should_have_same_units_when_order_size_does_not_breach_specific_short_limit_on_2nd_ccy_and_size_equals_default_limit_on_1sr_ccy(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits_short={'CHF': -234}) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 100, 'sell') filtered = rm.filter_order(order) self.assertEquals(100, filtered.units)
def test_should_have_appended_positions(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.append_position('EUR_CHF', 123) self.assertEquals(rm.positions['EUR_CHF'], 123)
def test_should_allow_to_append_positions_twice(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.append_position('EUR_CHF', 123) rm.append_position('EUR_CHF', 27) self.assertEquals(rm.positions['EUR_CHF'], 150)
def test_should_allow_to_append_different_positions(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.append_position('EUR_CHF', 123) rm.append_position('EUR_USD', 1000) self.assertEquals(rm.positions['EUR_CHF'], 123) self.assertEquals(rm.positions['EUR_USD'], 1000)
def step_impl(context): assert None != CcyExposureLimitRiskEvaluator('BC', context.rates_cache)
class TestRiskManager(unittest.TestCase): def assign_dummy_rates(self, rm): now = get_time() rm.rates_cache.set_rate(TickEvent('CHF_USD', now, 1.04, 1.05)) rm.rates_cache.set_rate(TickEvent('EUR_USD', now, 1.08, 1.09)) rm.rates_cache.set_rate(TickEvent('SGD_USD', now, 0.74, 0.75)) rm.rates_cache.set_rate(TickEvent('CHF_SGD', now, 1.04, 1.05)) def assign_unity_rates(self, rm): now = get_time() rm.rates_cache.set_rate(TickEvent('CHF_USD', now, 1.0, 1.0)) rm.rates_cache.set_rate(TickEvent('EUR_USD', now, 1.0, 1.0)) rm.rates_cache.set_rate(TickEvent('SGD_USD', now, 1.0, 1.0)) rm.rates_cache.set_rate(TickEvent('CHF_SGD', now, 1.0, 1.0)) def setUp(self): self.cache = FxPricesCache() self.rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-100000) self.assign_dummy_rates(self.rm) def test_currency_exposure_manager_exists(self): self.assertIsNotNone(CcyExposureLimitRiskEvaluator('BC', self.cache)) def test_should_have_base_currency(self): self.assertIsNotNone(CcyExposureLimitRiskEvaluator('BC', self.cache).base_ccy) self.assertEquals(CcyExposureLimitRiskEvaluator('BC', self.cache).base_ccy, 'BC') def test_should_have_currency_exposure_limit(self): self.assertIsNotNone(CcyExposureLimitRiskEvaluator('BC', self.cache).ccy_limit) def test_should_have_default_ccy_exposure_limit(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) self.assertTrue(rm.ccy_limit > 0) def test_should_have_preset_ccy_exposure_limit(self): rm = CcyExposureLimitRiskEvaluator('BC', FxPricesCache(), ccy_limit=123) self.assertEquals(rm.ccy_limit, 123) def test_should_not_allow_negative_preset_ccy_exposure_limit(self): try: CcyExposureLimitRiskEvaluator('BC', self.cache, ccy_limit=-123) except AssertionError: pass def test_should_have_specific_ccy_exposure_limits(self): self.assertIsNotNone(CcyExposureLimitRiskEvaluator('BC', self.cache).ccy_limits) def test_should_init_with_specific_ccy_exposure_limits(self): self.assertEquals(CcyExposureLimitRiskEvaluator('BC', self.cache, ccy_limits={}).ccy_limits, {}) def test_should_init_with_specific_ccy_exposure_limit_for_CHF(self): ccy_limits = {'CHF': 100.1} rm = CcyExposureLimitRiskEvaluator('BC', self.cache, ccy_limits=ccy_limits) self.assertEquals(rm.ccy_limits['CHF'], 100.1) def test_should_not_filter_order_without_rates(self): rmo = CcyExposureLimitRiskEvaluator('ABC', FxPricesCache()) try: rmo.filter_order(OrderEvent('CHF_USD', 1000, 'buy')) self.fail('Filtered order without fx rates') except AssertionError: pass def test_should_filter_order(self): filtered = self.rm.filter_order(OrderEvent('CHF_USD', 1000, 'buy')) self.assertIsNotNone(filtered, 'Could not filter trade') def test_filtered_order_should_have_expected_instrument(self): filtered = self.rm.filter_order(OrderEvent('CHF_USD', 100, 'buy')) self.assertEquals(filtered.instrument, 'CHF_USD') def test_filtered_buy_order_should_have_expected_side(self): filtered = self.rm.filter_order(OrderEvent('CHF_USD', 100, 'buy')) self.assertEquals(filtered.side, 'buy') def test_filtered_sell_order_should_have_expected_side(self): filtered = self.rm.filter_order(OrderEvent('CHF_USD', 100, 'sell')) self.assertEquals(filtered.side, 'sell') def test_filtered_order_should_have_expected_type(self): order = OrderEvent('CHF_USD', 100, 'buy') filtered = self.rm.filter_order(order) self.assertEquals(order.order_type, filtered.order_type) def test_filtered_order_should_have_same_units_when_order_size_does_not_breach_default_limit_on_1st_ccy(self): order = OrderEvent('CHF_USD', 100, 'buy') filtered = self.rm.filter_order(order) self.assertEquals(filtered.units, 100) def test_filtered_order_should_have_same_units_when_order_size_does_not_breach_non_default_limit_on_1st_ccy(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=150) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 140, 'buy') filtered = self.rm.filter_order(order) self.assertEquals(filtered.units, 140) def test_filtered_order_should_have_less_units_when_order_size_breaches_default_limit_on_1st_ccy(self): order = OrderEvent('EUR_SGD', 10000, 'buy') filtered = self.rm.filter_order(order) self.assertNotEquals(filtered.units, 10000) amount_in_base_ccy = round(self.rm.ccy_limit / self.rm.rates_cache.get_rate('EUR_USD')['ask'], 0) self.assertEquals(amount_in_base_ccy, filtered.units) def test_filtered_order_should_have_less_units_when_order_size_breaches_non_default_limit_on_1st_ccy(self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 1000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 1000) def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy(self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', ccy_limit=100, ccy_limits=ccy_limits) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') amount_in_base_ccy = round(rm.ccy_limits['CHF'] / self.rm.rates.get_rate('CHF_USD')['ask'], 0) filtered = rm.filter_order(order) self.assertEquals(amount_in_base_ccy, filtered.units) def test_filtered_sell_order_should_have_same_units_when_order_size_does_not_breach_default_short_limit_on_1st_ccy(self): order = OrderEvent('CHF_USD', 100, 'sell') filtered = self.rm.filter_order(order) self.assertEqual(100, filtered.units) def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy(self): ccy_limits_short = {'CHF': -234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits_short=ccy_limits_short) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 100, 'sell') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 100) def test_filtered_sell_order_should_have_same_units_when_order_size_does_not_breach_non_default_short_limit_on_1st_ccy(self): rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-10) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10, 'sell') filtered = self.rm.filter_order(order) self.assertEquals(filtered.units, 10) def test_filtered_sell_order_should_have_less_units_when_order_size_breaches_default_short_limit_on_1st_ccy(self): order = OrderEvent('EUR_SGD', 10000, 'sell') filtered = self.rm.filter_order(order) self.assertNotEquals(filtered.units, 10000) amount_in_base_ccy = round(self.rm.ccy_limit / self.rm.rates_cache.get_rate('SGD_USD')['ask'], 0) self.assertEquals(amount_in_base_ccy, filtered.units) def test_filtered_order_should_have_less_units_when_order_size_breaches_specific_limit_less_than_default_on_1st_ccy(self): ccy_limits = {'CHF': 100} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=1000, ccy_limits=ccy_limits) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 1000, 'buy') amount_in_base_ccy = round(rm.ccy_limits['CHF'] / self.rm.rates_cache.get_rate('CHF_USD')['ask'], 0) filtered = rm.filter_order(order) self.assertEquals(amount_in_base_ccy, filtered.units) def test_filtered_order_should_have_less_units_when_order_size_does_not_breach_specific_limit_more_than_default_on_1st_ccy_with_fx_rate_gt_1(self): ccy_limits = {'CHF': 10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=1000, ccy_limits=ccy_limits, ccy_limit_short=-10000) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) amount_in_base_ccy = round(rm.ccy_limits['CHF'] / rm.rates_cache.get_rate('CHF_USD')['ask'], 0) self.assertEquals(amount_in_base_ccy, filtered.units) def test_filtered_sell_order_should_have_less_units_when_order_size_breaches_short_specific_limit_less_than_default_short_limit_on_1st_ccy(self): ccy_limits_short = {'CHF': -100} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-1000, ccy_limits_short=ccy_limits_short) self.assign_dummy_rates(rm) order = OrderEvent('CHF_USD', 1000, 'sell') amount_in_base_ccy = round(-1 * rm.ccy_limits_short['CHF'] / self.rm.rates_cache.get_rate('CHF_USD')['bid'], 0) filtered = rm.filter_order(order) self.assertEquals(amount_in_base_ccy, filtered.units) self.assertEquals(filtered.instrument, 'CHF_USD') self.assertEquals(filtered.side, 'sell') def test_filtered_sell_order_should_have_same_units_when_order_size_breaches_short_specific_limit_more_than_default_short_limit_on_1st_ccy(self): ccy_limits_short = {'CHF': -10000} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit_short=-1000, ccy_limits_short=ccy_limits_short, ccy_limit=100000) self.assign_unity_rates(rm) order = OrderEvent('CHF_USD', 10000, 'sell') filtered = rm.filter_order(order) self.assertEquals(10000, filtered.units) self.assertEquals(filtered.instrument, 'CHF_USD') self.assertEquals(filtered.side, 'sell') def test_should_allow_to_set_ccy_limit_and_have_expected_value(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache, ccy_limits={}) rm.set_limit('CHF', 1234.5) self.assertEquals(rm.ccy_limits['CHF'], 1234.5) def test_filtered_order_should_have_less_units_when_order_size_breaches_both_specific_and_default_limit_on_1st_ccy(self): ccy_limits = {'CHF': 12000} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits, ccy_limit_short=-100000) self.assign_unity_rates(rm) order = OrderEvent('CHF_SGD', 15000, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 12000) def test_should_allow_to_set_unity_fx_rate_and_have_same_units(self): ccy_limits = {'CHF': 110} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits) rm.rates_cache.set_rate(TickEvent('CHF_SGD', get_time(), 1.0, 1.0)) order = OrderEvent('CHF_SGD', 105, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 105) def test_should_allow_to_set_unity_fx_rate_and_have_less_units_when_order_size_breaches_specific_limit_on_1st_ccy(self): ccy_limits = {'CHF': 110} rm = CcyExposureLimitRiskEvaluator('SGD', self.cache, ccy_limit=10000, ccy_limits=ccy_limits) rm.rates_cache.set_rate(TickEvent('CHF_SGD', get_time(), 1.0, 1.0)) order = OrderEvent('CHF_SGD', 150, 'buy') filtered = rm.filter_order(order) self.assertEquals(filtered.units, 110) def test_should_allow_second_instrument_without_breach_if_another_instrument_already_breached(self): order = OrderEvent('CHF_USD', 10000, 'buy') filtered = self.rm.filter_order(order) amount_in_base_ccy = round(self.rm.ccy_limit / self.rm.rates_cache.get_rate('CHF_USD')['ask']) self.assertEquals(filtered.units, amount_in_base_ccy) order = OrderEvent('EUR_SGD', 100, 'buy') filtered = self.rm.filter_order(order) self.assertEquals(filtered.units, 100) def test_should_allow_second_instrument_without_breach_if_first_instrument_breaches_specific_limit(self): ccy_limits = {'CHF': 1234} rm = CcyExposureLimitRiskEvaluator('USD', self.cache, ccy_limit=100, ccy_limits=ccy_limits) self.assign_unity_rates(rm) order = OrderEvent('CHF_USD', 10000, 'buy') filtered = rm.filter_order(order) amount_in_base_ccy = round(rm.ccy_limits['CHF'] / rm.rates_cache.get_rate('CHF_USD')['ask']) self.assertEquals(filtered.units, amount_in_base_ccy) rm.append_position(filtered.instrument, filtered.units) order = OrderEvent('EUR_SGD', 1000, 'buy') filtered = rm.filter_order(order) self.assertNotEquals(filtered.units, 1000) self.assertEquals(filtered.units, 100) def test_should_allow_to_set_short_ccy_limit_and_have_expected_value(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache, ccy_limits={}) rm.set_limit('CHF', ccy_limit_short=-1234.5) self.assertEquals(rm.ccy_limits_short['CHF'], -1234.5) def test_should_allow_to_set_long_short_ccy_limit_and_have_expected_value(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.set_limit('SHF_USD', ccy_limit=10000, ccy_limit_short=-22) self.assertEquals(rm.ccy_limits['SHF_USD'], 10000) self.assertEquals(rm.ccy_limits_short['SHF_USD'], -22) def test_should_allow_to_set_long_ccy_limit_and_unset_short_limit(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.set_limit('SHF_USD', ccy_limit_short=-22) self.assertEquals(rm.ccy_limits_short['SHF_USD'], -22) rm.set_limit('SHF_USD', ccy_limit=10000) self.assertEquals(rm.ccy_limits['SHF_USD'], 10000) self.assertFalse('SHF_USD' in rm.ccy_limits_short) def test_should_allow_to_set_short_ccy_limit_and_unset_long_limit(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.set_limit('SHF_USD', ccy_limit=10000) self.assertEquals(rm.ccy_limits['SHF_USD'], 10000) rm.set_limit('SHF_USD', ccy_limit_short=-22) self.assertEquals(rm.ccy_limits_short['SHF_USD'], -22) self.assertFalse('SHF_USD' in rm.ccy_limits) def test_should_allow_to_unset_ccy_limits(self): rm = CcyExposureLimitRiskEvaluator('BC', self.cache) rm.set_limit('SHF_USD', ccy_limit=10000 , ccy_limit_short=-22) self.assertEquals(rm.ccy_limits['SHF_USD'], 10000) self.assertEquals(rm.ccy_limits_short['SHF_USD'], -22) rm.set_limit('SHF_USD') self.assertFalse('SHF_USD' in rm.ccy_limits) self.assertFalse('SHF_USD' in rm.ccy_limits_short) def test_should_init_with_rates_cache(self): cache = FxPricesCache() self.assertEquals(CcyExposureLimitRiskEvaluator('BC', cache, ccy_limits={}).rates_cache, cache) """