def test_funds_under_risk(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=200, symbol='a2') f1 = Fund('f1', {'a1': 10, 'a2': 10, 'a3': 10}, 100, 1, 1) f2 = Fund('f2', {'a1': 10}, 100, 1, 1) network = AssetFundNetwork.AssetFundsNetwork( funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=MockMarketImpactTestCalculator()) network.reset_order_books = MagicMock() network.simulate_trade = MagicMock() network.submit_sell_orders = MagicMock() network.get_funds_in_margin_calls = MagicMock(return_value=['f1']) actions_mgr = ActionsManager(network.assets, 0.1) actual_funds = actions_mgr._ActionsManager__funds_under_risk(network) self.assertListEqual(actual_funds, ['f1']) network.reset_order_books.assert_called_once() network.submit_sell_orders.assert_called_once_with( [Sell('a1', 10), Sell('a2', 20)]) network.simulate_trade.assert_called_once() network.get_funds_in_margin_calls.assert_called_once()
def test_get_possible_attacks(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=10, symbol='a1') a1.set_price(3) a2 = AssetFundNetwork.Asset(price=2, daily_volume=4, symbol='a2') a2.set_price(4) a3 = AssetFundNetwork.Asset(price=7, daily_volume=2, symbol='a3') f1 = Fund('f1', {'a1': 10, 'a2': 10, 'a3': 10}, 100, 1, 1) f2 = Fund('f2', {'a1': 10}, 100, 1, 1) SysConfig.set("STEP_ORDER_SIZE", 0.5) network = AssetFundNetwork.AssetFundsNetwork( funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2, 'a3': a3 }, mi_calc=MockMarketImpactTestCalculator()) actual_orders = get_possible_attacks(network, 10) expected_orders = [] expected_orders.append(([Sell('a1', 5)], 5)) expected_orders.append(([Sell('a2', 2)], 4)) expected_orders.append(([Sell('a3', 1)], 7)) expected_orders.append(([Sell('a1', 5), Sell('a2', 2)], 9)) expected_orders.append(([], 0)) self.assertEqual(actual_orders, expected_orders)
def single_fund_attack_optimal_attack_generator(network: AssetFundsNetwork, fund_sym, mic: MarketImpactCalculator, order_size, max_num_orders): fund = network.funds[fund_sym] assets = network.assets fund_impacts = {} for a in assets.values(): shares_for_1M = floor(10000000 / a.zero_time_price) asset_price_impact = mic.get_market_impact( Sell(a.symbol, shares_for_1M), a.daily_volume) fund_impacts[ a. symbol] = 0 if a.symbol not in fund.portfolio else fund.portfolio[ a.symbol] * asset_price_impact sorted_impact = sorted(fund_impacts.items(), key=lambda x: x[1], reverse=True) cost = 0 actions = [] for sym, impact in sorted_impact: num_orders = 1 num_shares = floor(assets[sym].daily_volume * order_size) while num_orders <= max_num_orders: order = Sell(sym, num_shares) actions.append(order) cost += assets[sym].zero_time_price * num_shares network.submit_sell_orders([order]) network.clear_order_book() if fund.marginal_call(assets): return actions, cost num_orders += 1 return actions, cost
def test_get_possible_attacks_no_history(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=200, symbol='a2') assets = {'a1': a1, 'a2': a2} mgr = ActionsManager(assets, 0.1) expected_attacks = [([Sell('a1', 10)], 10), ([Sell('a2', 20)], 40), ([], 0)] actual_attacks = mgr.get_possible_attacks(budget=40) actual_attacks.sort(key=lambda a: a[1]) expected_attacks.sort(key=lambda a: a[1]) self.assertListEqual(expected_attacks, actual_attacks)
def test_get_single_orders(self): assets = {'a1': Asset(10, 100, 'a1'), 'a2': Asset(20, 200, 'a2')} expected_sell_orders = [Sell('a1', 10), Sell('a2', 20)] expected_buy_orders = [Buy('a1', 10), Buy('a2', 20)] actions_mgr = ActionsManager(assets, 0.1) actual_buy_orders = actions_mgr._ActionsManager__get_single_orders( assets, ActionsManager._ActionsManager__gen_buy_order) actual_sell_orders = actions_mgr._ActionsManager__get_single_orders( assets, ActionsManager._ActionsManager__gen_sell_order) self.assertListEqual(expected_sell_orders, actual_sell_orders) self.assertListEqual(expected_buy_orders, actual_buy_orders)
def test_get_possible_attacks(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=200, symbol='a2') a3 = AssetFundNetwork.Asset(price=3, daily_volume=300, symbol='a3') assets = {'a1': a1, 'a2': a2, 'a3': a3} mgr = ActionsManager(assets, 0.1) history = {BUY: {'a1': 2}, SELL: {'a1': 1, 'a2': 2}} expected_attacks = [([Sell('a1', 10)], 10), ([Sell('a3', 30)], 90), ([Sell('a1', 10), Sell('a3', 30)], 100), ([], 0)] actual_attacks = mgr.get_possible_attacks(100, history) actual_attacks.sort(key=lambda a: a[1]) expected_attacks.sort(key=lambda a: a[1]) self.assertListEqual(expected_attacks, actual_attacks)
def test_gen_liquidation_orders(self): SysConfig.set("MINUTE_VOLUME_LIMIT", 0.1) assets = { 'XXX': Asset(2, 3900, 1.5, 'XXX'), 'YYY': Asset(1, 7900, 1.5, 'yyy'), 'ZZZ': Asset(1, 7900, 1.5, 'yyy') } fund = Fund('F1', {'XXX': 10, 'YYY': 11, 'ZZZ': 2}, 5, 2, 0.25) expected_orders = [Sell('XXX', 1), Sell('YYY', 2), Sell('ZZZ', 2)] expected_portfolio = {'XXX': 9, 'YYY': 9} orders = fund.gen_liquidation_orders(assets) self.assertEqual(orders, expected_orders) self.assertEqual(fund.portfolio, expected_portfolio)
def test_get_attacks_in_budget(self): a1 = AssetFundNetwork.Asset(price=10, daily_volume=10, symbol='a1') a2 = AssetFundNetwork.Asset(price=20, daily_volume=10, symbol='a2') f1 = MockFund('f1', a1, 1) f2 = MockFund('f2', a2, 1) network = AssetFundNetwork.AssetFundsNetwork( funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=MockMarketImpactTestCalculator()) expected_portfolio = [ ([], 0), ([Sell("a1", 5)], 50), ([Sell("a1", 10)], 100), ([Sell("a2", 5)], 100), ([Sell("a2", 10)], 200), ([Sell("a1", 5), Sell("a2", 5)], 150), ([Sell("a1", 10), Sell("a2", 5)], 200), ] solver = SingleAgentESSolver(network, 0.5, 2) actual_portfolio = solver.get_attacks_in_budget(200, True) expected_portfolio_str = sorted([(str(x), str(y)) for (x, y) in expected_portfolio]) actual_portfolio_str = sorted([(str(x), str(y)) for (x, y) in actual_portfolio]) self.assertEqual(expected_portfolio_str, actual_portfolio_str)
def dont_test_get_possible_attacks_single_asset_per_attack(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=2, symbol='a1') f1 = Fund('f1', {'a1': 10}, 100, 1, 1) SysConfig.set("ORDER_SIZES", [0.5, 1]) network = AssetFundNetwork.AssetFundsNetwork( funds={'f1': f1}, assets={'a1': a1}, mi_calc=MockMarketImpactTestCalculator()) actual_sell_orders = get_possible_attacks(network, 10) expected_sell_orders = [] expected_sell_orders.append(([Sell('a1', 2)], 2)) expected_sell_orders.append(([Sell('a1', 1)], 1)) expected_sell_orders.append(([], 0)) self.assertEqual(actual_sell_orders, expected_sell_orders)
def test_gen_optimal_attacks(self): a1 = AssetFundNetwork.Asset(price=10, daily_volume=10, symbol='a1') a2 = AssetFundNetwork.Asset(price=20, daily_volume=10, symbol='a2') f1 = MockFund('f1', a1, 1) f2 = MockFund('f2', a2, 1) f2 = MockFund('f3', a2, 1) network = AssetFundNetwork.AssetFundsNetwork( funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=MockMarketImpactTestCalculator()) expected_portfolio = [ ([], 0), ([Sell("a1", 5)], 50), ([Sell("a1", 10)], 100), ([Sell("a2", 5)], 100), ([Sell("a2", 10)], 200), ([Sell("a1", 5), Sell("a2", 5)], 150), ([Sell("a1", 10), Sell("a2", 5)], 200), ]
def test_solution2(self): a1 = AssetFundNetwork.Asset(price=2, daily_volume=500, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=1000, symbol='a2') f1 = AssetFundNetwork.Fund('f1', {'a1': 10, 'a2': 10}, 16, 1, 1) f2 = AssetFundNetwork.Fund('f2', {'a1': 5, 'a2': 4}, 5, 2, 0.25) network = AssetFundNetwork.AssetFundsNetwork(funds = {'f1':f1, 'f2':f2}, assets={'a1':a1, 'a2':a2}, mi_calc=MockMarketImpactTestCalculator(), intraday_asset_gain_max_range=None, limit_trade_step=False ) actions,cost = single_fund_attack_optimal_attack_generator(network, 'f1', MockMarketImpactTestCalculator(),0.25,3) self.assertEqual(cost, 500) self.assertEqual(actions, [Sell('a1', 125),Sell('a1', 125)])
def test_simulate_trade_sell_orders_in_buy_command(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=1, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=1, symbol='a2') f1 = Fund('f1', {'a1': 10}, 100, 1, 1) f2 = Fund('f2', {'a2': 10}, 100, 1, 1) mi_calc = MarketImpactCalculator() mi_calc.get_updated_price = MagicMock() network = AssetFundNetwork.AssetFundsNetwork(funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=mi_calc, limit_trade_step=False) exception = False try: network.submit_buy_orders([Buy('a1', 2), Sell('a1', 2)]) except TypeError: exception = True mi_calc.get_updated_price.assert_not_called() self.assertTrue(exception)
def test_simulate_trade_sell_more_than_buy(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=1, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=1, symbol='a2') f1 = Fund('f1', {'a1': 10}, 100, 1, 1) f2 = Fund('f2', {'a2': 10}, 100, 1, 1) mi_calc = MarketImpactCalculator() mi_calc.get_updated_price = MagicMock(return_value=0.5) network = AssetFundNetwork.AssetFundsNetwork(funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=mi_calc, limit_trade_step=False) network.submit_buy_orders([Buy('a1', 2)]) network.submit_sell_orders([Sell('a1', 3)]) log = network.simulate_trade() self.assertDictEqual({'a1': '1->0.5'}, log) mi_calc.get_updated_price.assert_called_once_with(1, a1, -1) self.assertFalse(network.buy_orders) self.assertFalse(network.sell_orders) self.assertTrue(a1.price == 0.5) self.assertTrue(a2.price == 2)
def test_simulate_trade_buy_equals_sell(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=1, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=1, symbol='a2') f1 = Fund('f1', {'a1': 10}, 100, 1, 1) f2 = Fund('f2', {'a2': 10}, 100, 1, 1) mi_calc = MarketImpactCalculator() mi_calc.get_updated_price = MagicMock() network = AssetFundNetwork.AssetFundsNetwork(funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=mi_calc, limit_trade_step=False) network.submit_buy_orders([Buy('a1', 3)]) network.submit_sell_orders([Sell('a1', 3)]) log = network.simulate_trade() mi_calc.get_updated_price.assert_not_called() self.assertFalse(log) self.assertFalse(network.buy_orders) self.assertFalse(network.sell_orders) self.assertTrue(a1.price == 1) self.assertTrue(a2.price == 2)
def test_simulate_trade_mix_trades(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=1, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=1, symbol='a2') f1 = Fund('f1', {'a1': 10}, 100, 1, 1) f2 = Fund('f2', {'a2': 10}, 100, 1, 1) mi_calc = MarketImpactCalculator() mi_calc.get_updated_price = MagicMock(return_value=1.5) network = AssetFundNetwork.AssetFundsNetwork(funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=mi_calc, limit_trade_step=False) network.submit_sell_orders([Sell('a2', 2)]) network.submit_buy_orders([Buy('a1', 2)]) log = network.simulate_trade() calls = [call(2, a2, -1), call(2, a1, 1)] mi_calc.get_updated_price.assert_has_calls(calls, any_order=True) self.assertDictEqual({'a1': '1->1.5', 'a2': '2->1.5'}, log) self.assertFalse(network.buy_orders) self.assertFalse(network.sell_orders)
def build_attack_rec_wrong(self, n, c, network): if n == 0 or c == 0: s = Solution(network, [], 0) self.solutions[n][c] = s return s asset_sym = self.id_to_sym[n] if self.solutions[n][c]: return self.solutions[n][c] elif self.weights[n] > c: s = self.build_attack(n - 1, c, copy.deepcopy(network)) self.solutions[n][c] = s return s else: prev_solutions = {} max_result = self.build_attack(n - 1, c, copy.deepcopy(network)) prev_solutions[1] = self.build_attack(n - 1, c - self.weights[n], copy.deepcopy(network)) prev_solutions[2] = self.build_attack(n, c - self.weights[n], copy.deepcopy(network)) order = Sell( asset_sym, self.min_order_percentage * network.assets[asset_sym].daily_volume) for i in range(1, 2): net2 = prev_solutions[i].network net2.submit_sell_orders([order]) net2.clear_order_book() value = net2.count_margin_calls() if value > max_result.value: actions = copy.copy(prev_solutions[i].actions) actions.append(order) max_result = Solution(net2, actions, value) self.solutions[n][c] = max_result return max_result
def attack(self, n, network, orders_list): if n == 0: net2 = copy.deepcopy(network) net2.submit_sell_orders(orders_list) net2.clear_order_book() funds = net2.get_funds_in_margin_calls() cost = sum([ o.num_shares * network.assets[o.asset_symbol].zero_time_price for o in orders_list ]) value = len(funds) for i in range(1, value + 1): if i not in self.solutions or cost < self.solutions[i].cost: self.solutions[i] = Solution(network, orders_list, value, funds, cost) return asset_sym = self.id_to_sym[n] orders_list2 = copy.copy(orders_list) self.attack(n - 1, network, orders_list2) for i in range(1, self.max_order_num + 1): num_shares = int( floor(i * self.min_order_percentage * network.assets[asset_sym].daily_volume)) order = Sell(asset_sym, num_shares) orders_list2 = copy.copy(orders_list) orders_list2.append(order) self.attack(n - 1, network, orders_list2) return
def test_single_agent(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') a2 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') f1 = AssetFundNetwork.Fund('f1', {'a2': 10}, 100, 1, 1) f2 = AssetFundNetwork.Fund('f2', {'a1': 20}, 100, 1, 1) mi_calc = MarketImpactCalculator() mi_calc.get_updated_price = MagicMock() mi_calc.get_updated_price.side_effect = update_price_side_effects network = AssetFundNetwork.AssetFundsNetwork(funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=mi_calc, limit_trade_step=True) f1.marginal_call = MagicMock(return_value=False) f2.marginal_call = MagicMock() f2.marginal_call.side_effect = f1_margin_call_side_effect actions_mgr = ActionsManager(network.assets, 0.1, 2) result = single_agent(actions_mgr, network, 200) print(result.value) print(result.actions) self.assertEqual(result.value, -1) self.assertListEqual(result.actions, [[Sell('a1', 20)], ['MARKET']])
def test_get_portfolio_dict(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=100, symbol='a2') a3 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a3') a4 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a4') assets = {'a1': a1, 'a2': a2, 'a3': a3, 'a4': a4} actions_mgr = ActionsManager(assets, 0.1) attack1 = Attack([Sell('a1', 10)], 10) attack2 = Attack([Sell('a1', 10), Sell('a2', 10)], 40) attack3 = Attack([Sell('a3', 10)], 10) actions_mgr._ActionsManager__get_all_attacks = MagicMock( return_value=[attack1, attack2, attack3]) expected_dict = {10: [attack1, attack3], 40: [attack2]} actual_dict = dict( actions_mgr._ActionsManager__get_portfolio_dict(assets)) self.assertDictEqual(expected_dict, actual_dict) actions_mgr._ActionsManager__get_all_attacks.assert_called_once_with( assets, 4)
def test_filter_from_history(self): sell_action1 = Attack([Sell('a1', 1), Sell('a2', 1)], 10) sell_action2 = Attack([Sell('a1', 1), Sell('a3', 1)], 10) buy_action1 = Attack([Buy('a1', 1), Buy('a2', 1)], 10) buy_action2 = Attack([Buy('a2', 1)], 10) history = {BUY: {'a1': 2}, SELL: {'a1': 1, 'a2': 2}} self.assertTrue( ActionsManager._ActionsManager__filter_from_history( sell_action1, history, SELL)) self.assertFalse( ActionsManager._ActionsManager__filter_from_history( sell_action2, history, SELL)) self.assertTrue( ActionsManager._ActionsManager__filter_from_history( buy_action1, history, BUY)) self.assertFalse( ActionsManager._ActionsManager__filter_from_history( buy_action2, history, BUY))
def test_2(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=1, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=1, symbol='a2') f1 = MockFund('f1', a1, 1) f2 = MockFund('f2', a2, 1) network = AssetFundNetwork.AssetFundsNetwork( funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=MockMarketImpactTestCalculator()) solver = SingleAgentDynamicProgrammingSolver(network, 3, 1, 1) self.assertEqual(solver.results.value, 2) self.assertEqual(solver.results.actions[0], Sell('a1', 1)) self.assertEqual(solver.results.actions[1], Sell('a2', 1))
def test_gen_optimal_attacks(self): a1 = AssetFundNetwork.Asset(price=10, daily_volume=10, symbol='a1') a2 = AssetFundNetwork.Asset(price=20, daily_volume=10, symbol='a2') f1_margin_call = lambda assets: assets['a1'].price <= 8 f2_margin_call = lambda assets: assets['a2'].price <= 19 f3_margin_call = lambda assets: assets['a2'].price <= 19 mi_calc = MockMarketImpactTestCalculator({ 'a1': { 5: 9, 10: 8 }, 'a2': { 5: 19, 10: 18 } }) f1 = MockFund('f1', a1, f1_margin_call) f2 = MockFund('f2', a2, f2_margin_call) f3 = MockFund('f3', a2, f3_margin_call) network = AssetFundNetwork.AssetFundsNetwork(funds={ 'f1': f1, 'f2': f2, 'f3': f3 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=mi_calc, limit_trade_step=False) solver = SingleAgentESSolver(network, 0.5, 2) actual_solutions = solver.gen_optimal_attacks() solution_2 = Solution(network, [Sell('a2', 5)], 2, ['f2', 'f3'], 100) solution_3 = Solution(network, [Sell('a1', 10), Sell('a2', 5)], 3, ['f1', 'f2', 'f3'], 200) expected_solutions = {1: solution_2, 2: solution_2, 3: solution_3} self.assertEqual(expected_solutions, actual_solutions)
def gen_liquidation_orders(self, assets: Dict[str, Asset]): orders = [] assets_to_remove = [] for asset_symbol, num_shares in self.portfolio.items(): asset = assets[asset_symbol] shares_limit = floor(asset.avg_minute_volume * SysConfig.get("MINUTE_VOLUME_LIMIT")) shares_to_sell = min(shares_limit, num_shares) orders.append(Sell(asset_symbol, shares_to_sell)) self.portfolio[asset_symbol] -= shares_to_sell if self.portfolio[asset_symbol] == 0: assets_to_remove.append(asset_symbol) for asset_symbol in assets_to_remove: self.portfolio.pop(asset_symbol) return orders
def test_get_portfolios_in_budget_dict(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=200, symbol='a2') assets = {'a1': a1, 'a2': a2} mgr = ActionsManager(assets, 0.1, attacker_budgets=[5, 10]) id2portfolios = mgr.get_portfolios() actual = mgr.get_portfolios_in_budget_dict() expected_attacks_b5 = [Attack([], 0)] expected_attacks_b10 = [Attack([], 0), Attack([Sell('a1', 10)], 10)] actual_attacks_b5 = [id2portfolios[x] for x in actual[5]] actual_attacks_b10 = [id2portfolios[x] for x in actual[10]] self.assertListEqual(expected_attacks_b5, actual_attacks_b5) self.assertListEqual(expected_attacks_b10, actual_attacks_b10)
def get_all_attack_portfolios2(self, n, assets, budget, order_set): if n == 0: return order_set.append( self.get_all_attack_portfolios(n - 1, assets, budget, order_set)) asset_sym = self.id_to_sym[n] for i in range(1, self.max_order_num + 1): asset = assets[asset_sym] num_shares = int( floor(i * self.min_order_percentage * asset.daily_volume)) cost = num_shares * asset.zero_time_price if cost < budget: return order = Sell(asset_sym, num_shares) prev = self.get_all_attack_portfolios(n - 1, assets, budget - cost, order_set)
def test_order_limited_by_parameter(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=1, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=2, symbol='a2') f1 = MockFund(symbol='f1', my_asset=a1, margin_ratio=0.9) f2 = MockFund(symbol='f2', my_asset=a2, margin_ratio=0.9) network = AssetFundNetwork.AssetFundsNetwork( funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=MockMarketImpactTestCalculator()) solver = SingleAgentDynamicProgrammingSolver(network, 4, 0.5, 2) self.assertEqual(solver.results.value, 1) self.assertEqual(solver.results.actions[0], Sell('a2', 2))
def test_get_all_attacks(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=100, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=200, symbol='a2') a3 = AssetFundNetwork.Asset(price=3, daily_volume=300, symbol='a3') assets = {'a1': a1, 'a2': a2, 'a3': a3} expected_attacks = [ Attack([Sell('a1', 10)], 10), Attack([Sell('a2', 20)], 40), Attack([Sell('a3', 30)], 90), Attack([Sell('a1', 10), Buy('a2', 20)], 50), Attack([Sell('a1', 10), Buy('a3', 30)], 100), Attack([Sell('a2', 20), Buy('a3', 30)], 130), Attack( [Sell('a1', 10), Sell('a2', 20), Buy('a3', 30)], 140), Attack([], 0) ] mgr = ActionsManager(assets, 0.1) actual_attacks = mgr._ActionsManager__get_all_attacks(assets, 3) actual_attacks.sort(key=lambda a: a.cost) expected_attacks.sort(key=lambda a: a.cost) self.assertListEqual(actual_attacks, expected_attacks)
def build_attack(self, n, c, network): if n == 0 or c == 0: s = Solution(network, [], 0, [], 0) self.solutions[n][c] = s return s asset_sym = self.id_to_sym[n] if c in self.solutions[n]: return self.solutions[n][c] elif self.weights[n] > c: s = self.build_attack(n - 1, c, copy.deepcopy(network)) self.solutions[n][c] = s return s else: max_assets_orders = min(self.max_order_num, (int)(floor(c / self.weights[n]))) max_result = self.build_attack(n - 1, c, copy.deepcopy(network)) for i in range(1, max_assets_orders + 1): prev_solution = self.build_attack(n - 1, c - i * self.weights[n], copy.deepcopy(network)) num_shares = floor(i * self.min_order_percentage * network.assets[asset_sym].daily_volume) if not num_shares: continue order = Sell(asset_sym, num_shares) net2 = prev_solution.network net2.submit_sell_orders([order]) net2.clear_order_book() funds = net2.get_funds_in_margin_calls() value = len(funds) cost = prev_solution.cost + order.num_shares * network.assets[ order.asset_symbol].zero_time_price if value > max_result.value or (value == max_result.value and cost < max_result.cost): actions = copy.copy(prev_solution.actions) actions.append(order) max_result = Solution(net2, actions, value, funds, cost) self.solutions[n][c] = max_result return max_result
def test_reset_books(self): a1 = AssetFundNetwork.Asset(price=1, daily_volume=1, symbol='a1') a2 = AssetFundNetwork.Asset(price=2, daily_volume=1, symbol='a2') f1 = Fund('f1', {'a1': 10}, 100, 1, 1) f2 = Fund('f2', {'a2': 10}, 100, 1, 1) network = AssetFundNetwork.AssetFundsNetwork( funds={ 'f1': f1, 'f2': f2 }, assets={ 'a1': a1, 'a2': a2 }, mi_calc=MockMarketImpactTestCalculator(), limit_trade_step=True) network.submit_buy_orders([Buy('a1', 2)]) network.submit_sell_orders([Sell('a1', 2)]) self.assertTrue(network.sell_orders) self.assertTrue(network.buy_orders) network.reset_order_books() self.assertFalse(network.sell_orders) self.assertFalse(network.buy_orders)
def gen_tree(self, ): sell_order = Sell('a1', 50) sell = str([sell_order]) buy = str([Buy('a1', 50)]) nope = str([]) buy_actions = [nope, buy] root = { 'tree_size': 8, 'to_move': CHANCE, 'actions': ['p1', 'p2'], 'inf_set': '.', 'terminal': False } price_drop_log = "{'a1': '1->0.5'}" empty_log = '{}' node_1_0 = self.fill_dict(tree_size=6, to_move=ATTACKER, actions=[sell], history_assets_dict={ BUY: {}, SELL: {} }, players_info=PlayersHiddenInfo( attacker_attack=[sell_order], attacker_pid='p2', defender_budget=50), actions_history={ BUY: [], SELL: [], SIM_TRADE: [] }, inf_set='.p2.A_HISTORY:[]', terminal=False, eval=None) node_1_0_0 = self.fill_dict(tree_size=5, to_move=DEFENDER, actions=buy_actions, history_assets_dict={ BUY: {}, SELL: { 'a1': 1 } }, players_info=PlayersHiddenInfo( attacker_attack=[], attacker_pid='p2', defender_budget=50), actions_history={ BUY: [], SELL: [sell], SIM_TRADE: [] }, inf_set='.50.D_HISTORY:[]', terminal=False, eval=None) node_1_0_0_0 = self.fill_dict( tree_size=2, to_move=MARKET, actions=[empty_log], history_assets_dict={ BUY: { 'a1': 1 }, SELL: { 'a1': 1 } }, players_info=PlayersHiddenInfo(attacker_attack=[], attacker_pid='p2', defender_budget=0), actions_history={ BUY: [buy], SELL: [sell], SIM_TRADE: [] }, inf_set=".MARKET_HISTORY:[].BUY:{'a1': 50}.SELL:{'a1': 50}", terminal=False, eval=None) node_1_0_0_1 = self.fill_dict( tree_size=2, to_move=MARKET, actions=[price_drop_log], history_assets_dict={ BUY: {}, SELL: { 'a1': 1 } }, players_info=PlayersHiddenInfo(attacker_attack=[], attacker_pid='p2', defender_budget=50), actions_history={ BUY: [nope], SELL: [sell], SIM_TRADE: [] }, inf_set=".MARKET_HISTORY:[].BUY:{}.SELL:{'a1': 50}", terminal=False, eval=None) node_1_0_0_0_0 = self.fill_dict( tree_size=1, terminal=True, eval=0, to_move=ATTACKER, actions=[], history_assets_dict={ BUY: { 'a1': 1 }, SELL: { 'a1': 1 } }, players_info=PlayersHiddenInfo(attacker_attack=[], attacker_pid='p2', defender_budget=0), actions_history={ BUY: [buy, empty_log], SELL: [sell, empty_log], SIM_TRADE: [empty_log] }, inf_set=".p2.A_HISTORY:['[Sell a1 50]', '{}']") node_1_0_0_1_0 = self.fill_dict( tree_size=1, terminal=True, eval=-1, to_move=ATTACKER, actions=[], history_assets_dict={ BUY: { 'a1': 1 }, SELL: { 'a1': 1 } }, players_info=PlayersHiddenInfo(attacker_attack=[], attacker_pid='p2', defender_budget=50), actions_history={ BUY: [nope, price_drop_log], SELL: [sell, price_drop_log], SIM_TRADE: [price_drop_log] }, inf_set=".p2.A_HISTORY:['[Sell a1 50]', \"{'a1': '1->0.5'}\"]") ########### node_1_1 = self.fill_dict(tree_size=1, terminal=True, eval=0, to_move=ATTACKER, actions=[], history_assets_dict={ BUY: {}, SELL: {} }, players_info=PlayersHiddenInfo( attacker_attack=[], attacker_pid='p1', defender_budget=50), actions_history={ BUY: [], SELL: [], SIM_TRADE: [] }, inf_set='.p1.A_HISTORY:[]') ########## root['children'] = {'p2': node_1_0, 'p1': node_1_1} node_1_0['children'] = {sell: node_1_0_0} node_1_0_0['children'] = {buy: node_1_0_0_0, nope: node_1_0_0_1} node_1_0_0_0['children'] = {empty_log: node_1_0_0_0_0} node_1_0_0_1['children'] = {price_drop_log: node_1_0_0_1_0} node_1_0_0_0_0['children'] = {} node_1_0_0_1_0['children'] = {} node_1_1['children'] = {} return root