def calculate_signals(self, event): if event.TYPE != EVENT_TYPES_TICK: self.acknowledge(event) return instrument = getattr(event, 'instrument') if not instrument: raise RuntimeError( 'received event without attribute "instrument" - [%s]' % event) buy_sell_signal = self.strategy.calculate_signals(event) if buy_sell_signal: order = OrderEvent(instrument, self.units, buy_sell_signal) signal_units = order.get_signed_units() try: signal_amount_pending_ack = self.get_signaled_position( instrument) except KeyError: signal_amount_pending_ack = 0 if signal_amount_pending_ack != 0: if signal_units > 0 and signal_amount_pending_ack > 0: signal_units = 0 elif signal_units < 0 and signal_amount_pending_ack < 0: signal_units = 0 if signal_units != 0: self.logger.info('issuing order - %s' % order) self.update_signaled_position(order.instrument, order.get_signed_units()) return order
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_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_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_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_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_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_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_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_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_should_not_allow_to_create_with_none_units(self): try: OrderEvent('ABC', None, ORDER_SIDE_BUY) self.fail('should have failed') except AssertionError: pass except TypeError: pass
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_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_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_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_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_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_should_execute_and_parse_buy_order_USD_CHF(self): self.executor.connect() side = "buy" event = OrderEvent("USD_CHF", 125, side) executed_order = self.executor.execute_order_and_parse_response(event) self.executor.stop() self.assertIsNotNone(executed_order) self.assertIsInstance( executed_order, ExecutedOrder, 'expecting an executed order of type [%s] but got of type [%s] - %s' % (type(ExecutedOrder), type(executed_order), executed_order)) self.assertEqual(event, executed_order.order)
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_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 testOrderBuy_USD_CHF(self): self.executor.connect() side = "buy" event = OrderEvent("USD_CHF", 125, side) response = self.executor.execute_order(event) self.executor.stop() self.assertNotEqual(None, response) hasMessage = 'message' in response self.assertEqual(False, hasMessage, 'Unexpected response from broker - : %s' % response) self.assertEqual(response['instrument'], event.instrument) hasTradeOpened = 'tradeOpened' in response self.assertEqual(True, hasTradeOpened, "trade did not open by Oanda") trade = response['tradeOpened'] self.assertEqual(trade['units'], 125) self.assertEqual(trade['side'], side)
def testBuyLimitAndQueryOrder(self): self.executor.connect() side = "buy" expiry = get_time_with_zero_millis(100) event = OrderEvent("EUR_USD", 1000, side, order_type='limit', price=0.75, expiry=expiry) response = self.executor.execute_order(event) self.assertNotEqual(None, response) hasMessage = 'message' in response self.assertEqual(False, hasMessage, 'Unexpected response from broker - : %s' % response) self.assertEqual(response['instrument'], 'EUR_USD') hasOrderOpened = 'orderOpened' in response self.assertEqual(True, hasOrderOpened, "order did not open by Oanda") order = response['orderOpened'] self.assertEqual(order['units'], 1000) self.assertEqual(order['side'], side) self.assertEqual(order['expiry'], expiry) response = self.executor.get_order(order['id']) self.executor.stop() self.assertNotEqual(None, response) self.assertEqual(response['id'], order['id']) self.assertEqual(response['instrument'], 'EUR_USD') self.assertEqual(response['type'], 'limit') self.assertEqual(response['price'], 0.75) self.assertEqual(response['units'], 1000) self.assertEqual(response['side'], side) self.assertEqual(response['expiry'], expiry)
def test_should_get_orig_units_with_sign_sell_after_filter(self): order = OrderEvent('ABC', 1, ORDER_SIDE_SELL) order.units = 0 self.assertEquals(order.get_signed_orig_units(), -1)