예제 #1
0
 def test_should_not_accept_day_old_tick(self):
     cache = FxPricesCache()
     one_day_in_seconds = 86400
     one_day_ago = get_time(-1 * one_day_in_seconds)
     try:
         tick = TickEvent('CHF_USD', one_day_ago, 1.1, 1.2)
         cache.set_rate(tick)
         self.fail(
             'FX price cache should not have accepted a day old tick - [%s]'
             % tick)
     except AssertionError:
         pass
예제 #2
0
 def test_should_not_accept_tick_older_than_max_acceptable_age(self):
     max_tick_age = 100
     cache = FxPricesCache(max_tick_age=max_tick_age)
     older_than_max_tick_age = get_time(-2 * max_tick_age)
     try:
         tick = TickEvent('CHF_USD', older_than_max_tick_age, 1.1, 1.2)
         cache.set_rate(tick)
         self.fail(
             'FX price cache should not have accepted a tick older than [%s] seconds - [%s]'
             % (max_tick_age, tick))
     except AssertionError:
         pass
예제 #3
0
    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')
예제 #4
0
 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
예제 #5
0
    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')
예제 #6
0
 def wire(self, com_q=None, in_q=None, out_q=None, hb_q=None, e_q=None):
     rates_cache = FxPricesCache(max_tick_age=self.max_tick_age)
     rates_cache_loop = EventLoop(events_q=in_q,
                                  handler=rates_cache,
                                  forward_q=out_q)
     rates_cache_loop.set_command_q(com_q)
     self.component = rates_cache
     return rates_cache_loop
예제 #7
0
 def test_should_have_latest_of_twice_appended_rate(self):
     cache = FxPricesCache()
     cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))
     cache.set_rate(TickEvent('CHF_USD', get_time(), 1.15, 1.25))
     rates = cache.get_rate('CHF_USD')
     self.assertEqual(1.15, rates['bid'])
     self.assertEqual(1.25, rates['ask'])
예제 #8
0
    def play_event_loop(self, tick):
        events = Queue()
        cache = FxPricesCache()
        looper = EventLoop(events, cache)

        price_thread = Thread(target=looper.start, args=[])
        price_thread.start()

        events.put(tick)
        sleep(2 * looper.heartbeat)
        looper.stop()
        price_thread.join(timeout=2 * looper.heartbeat)
        return cache
예제 #9
0
 def test_should_init_with_rates_cache(self):
     cache = FxPricesCache()
     self.assertEquals(
         CcyExposureLimitRiskEvaluator('BC', cache,
                                       ccy_limits={}).rates_cache, cache)
예제 #10
0
 def test_should_give_error_when_rate_tuple_not_set(self):
     cache = FxPricesCache()
     try:
         cache.get_rate_tuple('CHF_USD')
     except KeyError:
         pass
예제 #11
0
 def test_should_have_appended_rate_tuple(self):
     cache = FxPricesCache()
     cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))
     rates = cache.get_rate_tuple('CHF_USD')
     self.assertEqual((1.1, 1.2), rates)
예제 #12
0
 def test_can_append_rate(self):
     cache = FxPricesCache()
     cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))
예제 #13
0
 def test_prices_cache_exists(self):
     self.assertIsNotNone(FxPricesCache())
예제 #14
0
 def test_should_have_preset_ccy_exposure_limit(self):
     rm = CcyExposureLimitRiskEvaluator('BC',
                                        FxPricesCache(),
                                        ccy_limit=123)
     self.assertEquals(rm.ccy_limit, 123)
예제 #15
0
 def test_accept_day_old_tick_if_less_than_max_acceptable_age(self):
     one_day_in_seconds = 86400
     cache = FxPricesCache(max_tick_age=2 * one_day_in_seconds)
     one_day_ago = get_time(-1 * one_day_in_seconds)
     tick = TickEvent('CHF_USD', one_day_ago, 1.1, 1.2)
     cache.set_rate(tick)
예제 #16
0
class TestFxPortfolio(unittest.TestCase):
    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 test_should_yield_positions_list_with_1_item_when_appended_executed_order(
            self):
        executed_order = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order)
        self.assertEqual(len(self.portfolio.list_positions()), 1)

    def test_should_yield_positions_list_with_1_item_when_appended_2_executed_order(
            self):
        executed_order1 = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.buy_50_CHF_USD, 1.15, 50)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(len(self.portfolio.list_positions()), 1)

    def test_should_yield_executions_list_with_2_matching_executions_when_appended_2_executions(
            self):
        executed_order1 = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.buy_50_CHF_USD, 1.15, 50)
        self.portfolio.append_position(executed_order2)
        executions = self.portfolio.list_executions()
        self.assertEqual(executed_order1, executions[0])
        self.assertEqual(executed_order2, executions[1])

    def test_should_yield_position_with_expected_units_when_appended_2_executed_buy_and_sell_order(
            self):
        executed_order1 = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.sell_50_CHF_USD, 1.15, 50)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(50, self.portfolio.list_position('CHF_USD'))

    def test_should_re_evaluate_long_position_when_new_market_rate_goes_up(
            self):
        executed_order = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.2, 1.3))
        revalued = self.portfolio.reval_position('CHF_USD')
        self.assertEqual(20, revalued)

    def test_should_give_average_execution_price_long_only(self):
        executed_order1 = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.buy_100_CHF_USD, 1.2, 100)
        self.portfolio.append_position(executed_order2)
        expected = round((100 * 1.1 + 100 * 1.2) / 200, 2)
        self.assertEqual(expected, self.portfolio.get_avg_price('CHF_USD'))

    def test_should_re_evaluates_all_positions_after_1_order_is_executed(self):
        executed_order = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.21, 1.22))
        self.portfolio.append_position(executed_order)
        expected = round(100 / 1.22 - 100, 2)
        self.assertEqual(expected, self.portfolio.reval_positions())

    def test_should_re_evaluates_all_positions_after_2_orders_are_executed_net_long(
            self):
        executed_order1 = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.sell_50_CHF_USD, 1.15, 50)
        self.portfolio.append_position(executed_order2)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.21, 1.22))
        expected = round(50 / 1.22 - 50, 2)
        self.assertEqual(expected, self.portfolio.reval_positions())

    def test_should_re_evaluates_all_positions_after_2_orders_are_executed_in_diff_ccy(
            self):
        executed_order1 = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.buy_100_EUR_USD, 0.9, 100)
        self.portfolio.append_position(executed_order2)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.21, 1.22))
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 0.91, 0.92))
        expected = round(100 / 1.22 + 100 / 0.92 - 200, 2)
        self.assertEqual(expected, self.portfolio.reval_positions())

    def test_should_re_evaluates_all_positions_after_2_orders_are_executed_in_diff_ccy_buy_sell(
            self):
        executed_order1 = ExecutedOrder(self.buy_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.sell_50_EUR_USD, 0.9, 50)
        self.portfolio.append_position(executed_order2)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.21, 1.22))
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 0.91, 0.92))
        expected = round(100 / 1.22 - 50 / 0.91 - 50, 2)
        self.assertEqual(expected, self.portfolio.reval_positions())

    def test_should_re_evaluates_all_positions_after_2_orders_are_executed_net_short(
            self):
        executed_order1 = ExecutedOrder(self.sell_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(self.buy_50_CHF_USD, 1.15, 50)
        self.portfolio.append_position(executed_order2)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.21, 1.22))
        expected = round(-50 / 1.21 + 50, 2)
        self.assertEqual(expected, self.portfolio.reval_positions())

    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 test_should_update_realized_pnl_when_appending_long_first_and_equal_short_second(
            self):
        executed_order = ExecutedOrder(self.buy_100_EUR_USD, 1.4, 100)
        executed_order2 = ExecutedOrder(self.sell_100_EUR_USD, 1.5, 100)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(10, self.portfolio.get_realized_pnl())

    def test_should_update_realized_pnl_when_appending_short_first_and_equal_long_second(
            self):
        executed_order = ExecutedOrder(self.sell_100_EUR_USD, 1.4, 100)
        executed_order2 = ExecutedOrder(self.buy_100_EUR_USD, 1.5, 100)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(10, self.portfolio.get_realized_pnl())

    def test_should_not_update_realized_pnl_when_execution_opposite_of_previously_open_position_but_diff_instrument(
            self):
        executed_order = ExecutedOrder(self.buy_100_EUR_USD, 1.4, 100)
        executed_order2 = ExecutedOrder(self.sell_100_CHF_USD, 1.1, 100)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(0, self.portfolio.get_realized_pnl())

    def test_should_update_realized_pnl_when_closing_one_position_while_another_open_position_in_diff_instrument_exists(
            self):
        executed_order = ExecutedOrder(self.buy_100_EUR_USD, 1.4, 100)
        executed_order2 = ExecutedOrder(self.sell_100_CHF_USD, 1.1, 100)
        executed_order3 = ExecutedOrder(self.sell_100_EUR_USD, 1.45, 100)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.portfolio.append_position(executed_order3)
        self.assertEqual(5, self.portfolio.get_realized_pnl())

    def test_should_update_negative_realized_pnl_when_appending_closing_position_at_loss(
            self):
        executed_order = ExecutedOrder(self.buy_100_EUR_USD, 1.4, 100)
        executed_order2 = ExecutedOrder(self.sell_100_EUR_USD, 1.3, 100)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(-10, self.portfolio.get_realized_pnl())

    def test_should_have_zero_unrealized_pnl_after_closing_position(self):
        executed_order = ExecutedOrder(self.buy_100_EUR_USD, 1.4, 100)
        executed_order2 = ExecutedOrder(self.sell_100_EUR_USD, 1.3, 100)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 0.91, 0.92))
        self.assertEqual(0, self.portfolio.reval_positions())

    def test_should_have_correct_realized_pnl_after_partial_close(self):
        executed_order = ExecutedOrder(self.buy_100_EUR_USD, 1.4, 100)
        executed_order2 = ExecutedOrder(self.sell_50_EUR_USD, 1.3, 50)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 0.91, 0.92))
        self.assertEqual(-5, self.portfolio.get_realized_pnl())

    def test_should_have_correct_unrealized_pnl_after_partial_close(self):
        executed_order = ExecutedOrder(self.buy_100_EUR_USD, 0.905, 100)
        executed_order2 = ExecutedOrder(self.sell_50_EUR_USD, 0.900, 50)
        self.portfolio.append_position(executed_order)
        self.portfolio.append_position(executed_order2)
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 0.910, 0.920))
        expected = round(50 / 0.920 - 50, 2)
        self.assertEqual(expected, self.portfolio.reval_positions())
예제 #17
0
class TestFxPortfolio(unittest.TestCase):
    def setUp(self):
        self.portfolio = FxPortfolio('USD', 10000)
        self.cache = FxPricesCache()
        self.portfolio.set_price_cache(self.cache)

    def test_should_yields_empty_list_when_no_trade_exists(self):
        self.assertIsNotNone(self.portfolio.list_positions())
        self.assertEqual(0, len(self.portfolio.list_positions()))

    def test_should_append_executed_order(self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)

    def test_should_yield_not_none_positions_list_when_appended_executed_order(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.assertIsNotNone(self.portfolio.list_positions())

    def test_should_yield_non_empty_positions_list_when_appended_executed_order(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.assertIsNotNone(self.portfolio.list_positions())
        self.assertTrue(len(self.portfolio.list_positions()) > 0)

    def test_should_yield_not_none_executions_list_when_appended_executed_order(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.assertIsNotNone(self.portfolio.list_executions())

    def test_should_yield_non_empty_executions_list_when_appended_executed_order(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.assertIsNotNone([], self.portfolio.list_positions())
        self.assertTrue(len(self.portfolio.list_executions()) > 0)

    def test_should_yield_executions_list_with_1_item_when_appended_executed_order(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.assertEqual(len(self.portfolio.list_executions()), 1)

    def test_should_yield_executions_list_with_2_items_when_appended_2_executed_order(
            self):
        executed_order1 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                        100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'),
                                        1.15, 50)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(len(self.portfolio.list_executions()), 2)

    def test_should_yield_position_with_expected_units_when_appended_executed_order(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.assertEqual(100, self.portfolio.list_position('CHF_USD'))

    def test_should_yield_position_with_expected_units_when_appended_2_executed_order(
            self):
        executed_order1 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                        100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'),
                                        1.15, 50)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(150, self.portfolio.list_position('CHF_USD'))

    def test_should_yield_position_with_expected_units_when_appended_2_executed_buy_and_sell_order_negative_pos(
            self):
        executed_order1 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'sell'),
                                        1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(OrderEvent('CHF_USD', 50, 'buy'), 1.15,
                                        50)
        self.portfolio.append_position(executed_order2)
        self.assertEqual(-50, self.portfolio.list_position('CHF_USD'))

    def test_should_give_average_execution_price_long_short(self):
        executed_order1 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                        100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(OrderEvent('CHF_USD', 50, 'sell'), 1.2,
                                        50)
        self.portfolio.append_position(executed_order2)
        expected = 1.1
        self.assertEqual(50, self.portfolio.list_position('CHF_USD'))
        self.assertEqual(expected, self.portfolio.get_avg_price('CHF_USD'))

    def test_should_give_average_execution_price_short_long(self):
        executed_order1 = ExecutedOrder(OrderEvent('CHF_USD', 50, 'sell'), 1.1,
                                        50)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.2,
                                        100)
        self.portfolio.append_position(executed_order2)
        expected = 1.2
        self.assertEqual(50, self.portfolio.list_position('CHF_USD'))
        self.assertEqual(expected, self.portfolio.get_avg_price('CHF_USD'))

    def test_should_give_average_execution_price_long_less_than_short(self):
        executed_order1 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                        100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(OrderEvent('CHF_USD', 150, 'sell'),
                                        1.2, 150)
        self.portfolio.append_position(executed_order2)
        expected = 1.2
        self.assertEqual(-50, self.portfolio.list_position('CHF_USD'))
        self.assertEqual(expected, self.portfolio.get_avg_price('CHF_USD'))

    def test_should_give_average_execution_price_short_only(self):
        executed_order1 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'sell'),
                                        1.1, 100)
        self.portfolio.append_position(executed_order1)
        executed_order2 = ExecutedOrder(OrderEvent('CHF_USD', 100, 'sell'),
                                        1.2, 100)
        self.portfolio.append_position(executed_order2)
        expected = abs(round((-100 * 1.1 - 100 * 1.2) / 200, 2))
        self.assertEqual(expected, self.portfolio.get_avg_price('CHF_USD'))

    def test_should_re_evaluate_short_position_when_new_market_rate_goes_up(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'sell'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.2, 1.3))
        revalued = self.portfolio.reval_position('CHF_USD')
        self.assertEqual(-10, revalued)

    def test_should_re_evaluate_long_position_when_new_market_rate_goes_down(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'buy'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.051, 1.064))
        revalued = self.portfolio.reval_position('CHF_USD')
        expected = round(100 * (1.064 - 1.1), 2)
        self.assertEqual(expected, revalued)

    def test_should_re_evaluate_short_position_when_new_market_rate_goes_down(
            self):
        executed_order = ExecutedOrder(OrderEvent('CHF_USD', 100, 'sell'), 1.1,
                                       100)
        self.portfolio.append_position(executed_order)
        self.cache.set_rate(TickEvent('CHF_USD', get_time(), 1.051, 1.064))
        revalued = self.portfolio.reval_position('CHF_USD')
        expected = round(-100 * (1.051 - 1.1), 2)
        self.assertEqual(expected, revalued)

    def test_should_have_portfolio_limit(self):
        self.assertIsNotNone(self.portfolio)

    def test_should_have_default_portfolio_limit(self):
        self.assertTrue(self.portfolio.port_limit > 0)

    def test_should_have_preset_portfolio_limit(self):
        portfolio = FxPortfolio('USD', 10000, port_limit=1230)
        self.assertEquals(portfolio.port_limit, 1230)

    def test_should_give_realized_pnl(self):
        self.assertIsNotNone(self.portfolio.get_realized_pnl())

    def test_should_have_balance(self):
        self.assertIsNotNone(self.portfolio.get_balance())
예제 #18
0
 def setUp(self):
     self.portfolio = FxPortfolio('USD', 10000)
     self.cache = FxPricesCache()
     self.portfolio.set_price_cache(self.cache)
예제 #19
0
def step_impl(context):
    context.rates_cache = FxPricesCache()
예제 #20
0
 def setUp(self):
     self.cache = FxPricesCache()
 def setUp(self):
     self.cache = FxPricesCache()
     self.rm = CcyExposureLimitRiskEvaluator('USD',
                                             self.cache,
                                             ccy_limit_short=-100000)
     self.assign_dummy_rates(self.rm)
예제 #22
0
class TestFxPricesCache(unittest.TestCase):
    def setUp(self):
        self.cache = FxPricesCache()

    def test_prices_cache_exists(self):
        self.assertIsNotNone(FxPricesCache())

    def test_can_append_rate(self):
        cache = FxPricesCache()
        cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))

    def test_should_have_appended_rate(self):
        cache = FxPricesCache()
        cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))
        rates = cache.get_rate('CHF_USD')
        self.assertEqual(1.1, rates['bid'])
        self.assertEqual(1.2, rates['ask'])

    def test_should_have_appended_rate_tuple(self):
        cache = FxPricesCache()
        cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))
        rates = cache.get_rate_tuple('CHF_USD')
        self.assertEqual((1.1, 1.2), rates)

    def test_should_have_latest_of_twice_appended_rate(self):
        cache = FxPricesCache()
        cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))
        cache.set_rate(TickEvent('CHF_USD', get_time(), 1.15, 1.25))
        rates = cache.get_rate('CHF_USD')
        self.assertEqual(1.15, rates['bid'])
        self.assertEqual(1.25, rates['ask'])

    def test_should_have_latest_of_twice_appended_rate_tuple(self):
        cache = FxPricesCache()
        cache.set_rate(TickEvent('CHF_USD', get_time(), 1.1, 1.2))
        cache.set_rate(TickEvent('CHF_USD', get_time(), 1.15, 1.25))
        rates = cache.get_rate_tuple('CHF_USD')
        self.assertEqual((1.15, 1.25), rates)

    def test_should_give_error_when_rate_not_set(self):
        cache = FxPricesCache()
        try:
            cache.get_rate('CHF_USD')
        except KeyError:
            pass

    def test_should_give_error_when_rate_tuple_not_set(self):
        cache = FxPricesCache()
        try:
            cache.get_rate_tuple('CHF_USD')
        except KeyError:
            pass

    def test_give_unity_for_same_ccy(self):
        self.assertEqual(self.cache.get_rate('CHF_CHF'), {
            'bid': 1.0,
            'ask': 1.0
        })

    def test_give_unity_tuple_for_same_ccy(self):
        self.assertEqual(self.cache.get_rate_tuple('CHF_CHF'), (1.0, 1.0))

    def test_should_not_accept_day_old_tick(self):
        cache = FxPricesCache()
        one_day_in_seconds = 86400
        one_day_ago = get_time(-1 * one_day_in_seconds)
        try:
            tick = TickEvent('CHF_USD', one_day_ago, 1.1, 1.2)
            cache.set_rate(tick)
            self.fail(
                'FX price cache should not have accepted a day old tick - [%s]'
                % tick)
        except AssertionError:
            pass

    def test_should_not_accept_tick_older_than_max_acceptable_age(self):
        max_tick_age = 100
        cache = FxPricesCache(max_tick_age=max_tick_age)
        older_than_max_tick_age = get_time(-2 * max_tick_age)
        try:
            tick = TickEvent('CHF_USD', older_than_max_tick_age, 1.1, 1.2)
            cache.set_rate(tick)
            self.fail(
                'FX price cache should not have accepted a tick older than [%s] seconds - [%s]'
                % (max_tick_age, tick))
        except AssertionError:
            pass

    def test_accept_day_old_tick_if_less_than_max_acceptable_age(self):
        one_day_in_seconds = 86400
        cache = FxPricesCache(max_tick_age=2 * one_day_in_seconds)
        one_day_ago = get_time(-1 * one_day_in_seconds)
        tick = TickEvent('CHF_USD', one_day_ago, 1.1, 1.2)
        cache.set_rate(tick)
예제 #23
0
class TestFxPortfolio(unittest.TestCase):
    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 test_should_reduce_units_of_very_large_buy_order(self):
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.check_order(self.large_buy_order)
            self.assertEqual(self.ccy_exposure_manager.ccy_limit,
                             filtered_order.units)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_reduce_units_of_very_large_sell_order(self):
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.check_order(self.large_sell_order)
            self.assertEqual(self.ccy_exposure_manager.ccy_limit_short,
                             -1 * filtered_order.units)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_return_correct_order_after_checking(self):
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.check_order(self.buy_order)
            self.assertEqual(self.buy_order.units, filtered_order.units)
            self.assertEqual(self.buy_order.instrument,
                             filtered_order.instrument)
            self.assertEqual(self.buy_order.side, filtered_order.side)
            self.assertEqual(self.buy_order.order_type,
                             filtered_order.order_type)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_return_correct_order_after_processing(self):
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.process(self.buy_order)
            self.assertEqual(self.buy_order.units, filtered_order.units)
            self.assertEqual(self.buy_order.instrument,
                             filtered_order.instrument)
            self.assertEqual(self.buy_order.side, filtered_order.side)
            self.assertEqual(self.buy_order.order_type,
                             filtered_order.order_type)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_reduce_units_of_large_buy_order_using_position_limit_manager(
            self):
        rm = FxPositionLimitRiskEvaluator(posLimit=100)
        self.portfolio.add_risk_manager(rm)
        order = OrderEvent('EUR_USD', 1000, 'buy')
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.check_order(order)
            self.assertEqual(rm.posLimit, filtered_order.units)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_reduce_units_of_large_sell_order_using_position_limit_manager(
            self):
        rm = FxPositionLimitRiskEvaluator(posLimitShort=-100)
        self.portfolio.add_risk_manager(rm)
        order = OrderEvent('EUR_USD', 1000, 'sell')
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.check_order(order)
            self.assertEqual(rm.posLimitShort, -1 * filtered_order.units)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_reduce_units_of_large_buy_order_using_ccy_exposure_manager_when_pos_limit_manager_is_generous(
            self):
        rm = FxPositionLimitRiskEvaluator(posLimit=1000000)
        self.portfolio.add_risk_manager(rm)
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.check_order(self.large_buy_order)
            self.assertEqual(self.ccy_exposure_manager.ccy_limit,
                             filtered_order.units)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_reduce_units_of_large_sell_order_using_ccy_exposure_manager_when_pos_limit_manager_is_generous(
            self):
        rm = FxPositionLimitRiskEvaluator(posLimitShort=-1000000)
        self.portfolio.add_risk_manager(rm)
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.0, 1.0))
        try:
            filtered_order = self.portfolio.check_order(self.large_sell_order)
            self.assertEqual(self.ccy_exposure_manager.ccy_limit_short,
                             -1 * filtered_order.units)
        except RuntimeError as e:
            self.fail(
                'Expecting a filtered order per currency manager\'s limit, but got exception - [%s]'
                % e)

    def test_should_be_able_to_process_fills(self):
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.11, 1.15))
        executed_order = ExecutedOrder(self.buy_order, 1.12, 100)

        processed_value = self.portfolio.process(executed_order)
        self.assertIsNone(processed_value)
        self.assertEqual({'EUR_USD': 100}, self.portfolio.list_positions())

    def test_should_be_able_to_process_fills_or_signals(self):
        self.cache.set_rate(TickEvent('EUR_USD', get_time(), 1.11, 1.15))

        # process a signal first
        processed_value = self.portfolio.process(self.buy_order)
        self.assertEqual(self.buy_order.units, processed_value.units)
        self.assertEqual(self.buy_order.instrument, processed_value.instrument)
        self.assertEqual(self.buy_order.side, processed_value.side)
        self.assertEqual(self.buy_order.order_type, processed_value.order_type)

        # process a fill now
        executed_order = ExecutedOrder(processed_value, 1.12, 100)
        processed_value = self.portfolio.process(executed_order)
        self.assertIsNone(processed_value)
        self.assertEqual({'EUR_USD': 100}, self.portfolio.list_positions())

    def test_should_not_allow_to_add_same_risk_manager(self):
        rm = FxPositionLimitRiskEvaluator(posLimitShort=-1000000)
        self.portfolio.add_risk_manager(rm)
        try:
            self.portfolio.add_risk_manager(rm)
            self.fail('Should have failed while adding same risk manager')
        except:
            pass