Esempio n. 1
0
    def __init__(self):
        self._stock_levels = {}
        self._sides = item.initialise_sides(self._stock_levels)
        self._drinks = item.initialise_drinks(self._stock_levels)
        self._ingredients = item.initialise_ingredients(self._stock_levels)
        self._buns = item.initialise_buns(self._stock_levels)
        self._order_manager = OrderManager()
        self._lookup = {}
        obj_list = (*self._sides, *self._drinks, *self._ingredients,
                    *self._buns)
        for obj in obj_list:
            self._lookup[obj.name] = obj

        standard_burger_buns = [self.get_object_by_name("Sesame bun")] * 2
        standard_burger_fillings = [
            self.get_object_by_name(name)
            for name in ("Beef Patty", "Cheddar Cheese", "Tomato Sauce")
        ]
        standard_wrap_fillings = [
            self.get_object_by_name(name)
            for name in ("Chicken Patty", "Tomato", "Lettuce")
        ]

        self._standard_burger = Burger(standard_burger_fillings,
                                       standard_burger_buns)
        self._standard_wrap = Wrap(standard_wrap_fillings)
Esempio n. 2
0
class TestOrderBook(unittest.TestCase):

    def setUp(self):
        self.order_manager = OrderManager()

    def test_receive_order_from_trading_strategy(self):
        order1 = {
            'id': 10,
            'price': 219,
            'quantity': 10,
            'side': 'bid',
        }
        self.order_manager.handle_order_from_trading_strategy(order1)
        self.assertEqual(len(self.order_manager.orders),1)
        self.order_manager.handle_order_from_trading_strategy(order1)
        self.assertEqual(len(self.order_manager.orders),2)
        self.assertEqual(self.order_manager.orders[0]['id'],1)
        self.assertEqual(self.order_manager.orders[1]['id'],2)

    def test_receive_order_from_trading_strategy_error(self):
        order1 = {
            'id': 10,
            'price': -219,
            'quantity': 10,
            'side': 'bid',
        }
        self.order_manager.handle_order_from_trading_strategy(order1)
        self.assertEqual(len(self.order_manager.orders),0)

    def display_orders(self):
        for o in self.order_manager.orders:
            print(o)

    def test_receive_from_gateway_filled(self):
        self.test_receive_order_from_trading_strategy()
        orderexecution1 = {
            'id': 2,
            'price': 13,
            'quantity': 10,
            'side': 'bid',
            'status' : 'filled'
        }
        # self.display_orders()
        self.order_manager.handle_order_from_gateway(orderexecution1)
        self.assertEqual(len(self.order_manager.orders), 1)

    def test_receive_from_gateway_acked(self):
        self.test_receive_order_from_trading_strategy()
        orderexecution1 = {
            'id': 2,
            'price': 13,
            'quantity': 10,
            'side': 'bid',
            'status' : 'acked'
        }
        # self.display_orders()
        self.order_manager.handle_order_from_gateway(orderexecution1)
        self.assertEqual(len(self.order_manager.orders), 2)
        self.assertEqual(self.order_manager.orders[1]['status'], 'acked')
Esempio n. 3
0
    def setUp(self):
        self.order_manager = OrderManager()

        self.person_1 = new_person(
                {'username': '******', 'name': 'Name1', 'surname': 'Surname1', 'password': '******',
                 'passwordRetype': 'test123', 'email': '*****@*****.**'})

        self.person_1.number_of_stocks = 5
        self.person_1.save()

        self.person_2 = new_person(
                {'username': '******', 'name': 'Name2', 'surname': 'Surname2', 'password': '******',
                 'passwordRetype': 'test123', 'email': '*****@*****.**'})

        self.person_3 = new_person(
                {'username': '******', 'name': 'Name3', 'surname': 'Surname3', 'password': '******',
                 'passwordRetype': 'test123', 'email': '*****@*****.**'})

        self.bidding_round = BiddingRound.objects.create(is_active=True)

        stock_order_1 = StockOrder()
        stock_order_1.owner = self.person_1
        stock_order_1.order_type = BUY
        stock_order_1.order_price_per_share = 8.5
        stock_order_1.order_amount_of_shares = 10
        stock_order_1.bidding_round = self.bidding_round

        stock_order_2 = StockOrder()
        stock_order_2.owner = self.person_1
        stock_order_2.order_type = BUY
        stock_order_2.order_price_per_share = 7.5
        stock_order_2.order_amount_of_shares = 5
        stock_order_2.bidding_round = self.bidding_round

        stock_order_3 = StockOrder()
        stock_order_3.owner = self.person_1
        stock_order_3.order_type = BUY
        stock_order_3.order_price_per_share = 6.5
        stock_order_3.order_amount_of_shares = 15
        stock_order_3.bidding_round = self.bidding_round

        stock_order_arch = StockOrder()
        stock_order_arch.owner = self.person_1
        stock_order_arch.order_type = SELL
        stock_order_arch.order_price_per_share = 5
        stock_order_arch.order_amount_of_shares = 100
        stock_order_arch.bidding_round = self.bidding_round
        stock_order_arch.is_archived = True

        self.order_1_person_1 = self.order_manager.place_order(stock_order_1)
        self.order_2_person_1 = self.order_manager.place_order(stock_order_2)
        self.order_3_person_1 = self.order_manager.place_order(stock_order_3)
        self.order_archived_person_1 = create_stock_order(stock_order_arch)

        self.order_1_person_2 = StockOrder.objects.create(owner=self.person_2)
        self.order_2_person_2 = StockOrder.objects.create(owner=self.person_2)

        self.order_1_person_3 = StockOrder.objects.create(owner=self.person_2)
Esempio n. 4
0
    def test_checker(self):
        #we expect the first order created to have an id of 0
        self.x = OrderManager()

        assert self.x.id_exists('0') == False

        self.x.create_new_order()

        assert self.x.id_exists('0') == True
    def __init__(self):
        # 股票 -> 策略
        self.strategy_instance = StrategyFactory().create()
        # 股票 -> 仓位
        self.stock_position_dic = {}
        # 订单管理
        self.order_manager = OrderManager(self.stock_position_dic)

        self.quote_manager = QuoteManager()

        self.cumPNL = 0
Esempio n. 6
0
    def test_setters(self):
        self.x = OrderManager()

        id1 = self.x.create_new_order()

        assert len(self.x.orders) == 1
        assert type(self.x.orders[0]) == Order
        assert type(self.x.get_order_by_id(id1)) == Order

        id2 = self.x.create_new_order()

        assert len(self.x.orders) == 2
Esempio n. 7
0
    def test_invalid_cases(self):
        self.x = OrderManager()

        with pytest.raises(TypeError):
            self.x.get_order_by_id('1.1')

        with pytest.raises(TypeError):
            self.x.get_order_by_id(1.1)

        with pytest.raises(KeyError):
            self.x.get_order_by_id('1')

        assert self.x.id_exists('a') == False
Esempio n. 8
0
 def process_order(self, order, delay=0):
     order_manager = OrderManager(self)
     is_acknowledged = order_manager.acknowledge_order(order)
     time.sleep(delay)
     if is_acknowledged:
         print("order is acknowledged")
         print(order.acknowledged)
         print(order.rejected)
         print(order_manager.warehouses)
         order_manager.ship_order(order=order)
     else:
         print("There is no inventory for this order")
         print(order.acknowledged)
         print(order.rejected)
         print(order_manager.warehouses)
Esempio n. 9
0
    def setUp(self):
        self.lp_2_gateway = deque()
        self.ob_2_ts = deque()
        self.ts_2_om = deque()
        self.ms_2_om = deque()
        self.om_2_ts = deque()
        self.gw_2_om = deque()
        self.om_2_gw = deque()

        self.liquidityProvider = LiquidityProvider(self.lp_2_gateway)
        self.bookBuilder = OrderBook(self.lp_2_gateway, self.ob_2_ts)
        self.tradingStrategy = TradingStrategy(self.ob_2_ts, self.ts_2_om,
                                               self.om_2_ts)
        self.marketSimulator = MarketSimulator(self.om_2_gw, self.gw_2_om)
        self.orderManager = OrderManager(self.ts_2_om, self.om_2_ts,
                                         self.om_2_gw, self.gw_2_om)
Esempio n. 10
0
def main():

    try:
        market = sys.argv[1]
    except IndexError:
        market = 'not a currency pair'

    if market not in constants.MARKETS:
        while True:
            market = str(
                input(
                    "Please specify which currency pair to use (btcusd, ltcusd, etc)."
                ))
            if market in constants.MARKETS:
                break

    running = True

    md = MarketDataInterface(market)
    ts = TradingStrategy(market)
    om = OrderManager(market)

    while running:
        action = ts.get_final_strategy()
        price = (md.get_ticker_data(False))['value']
        order_details = om.get_order_status(id)

        if action['action'] == "buy":
            result = om.buy(pair=market, risk=action['risk'], price=price)
            order_details = om.get_order_status(result)
            if result[0]:
                logging.info('Successfully bought {0}{1} at {2}{3}'.format(
                    order_details['actual_amount'], market[:3],
                    order_details['actual_end_price'], market[-3:]))
            else:
                logging.info('Buy failed')

        elif action['action'] == "sell":
            result = om.sell(pair=market, risk=action['risk'], price=price)
            order_details = om.get_order_status(result)
            if result:
                logging.info('Successfully sold {0}{1} at {2}{3}'.format(
                    order_details['amount'], market[:3],
                    order_details['price'], market[-3:]))
            else:
                logging.info('Sell failed')

        elif action['action'] == "wait":
            logging.info('Waited {}s, did not trade'.format(
                settings.MAIN_TIMER))

        else:
            running = False
            logging.error('Unsupported action')

        time.sleep(settings.MAIN_TIMER)
        if not running:
            print('order error')
class StrategyManager:
    def __init__(self):
        # 股票 -> 策略
        self.strategy_instance = StrategyFactory().create()
        # 股票 -> 仓位
        self.stock_position_dic = {}
        # 订单管理
        self.order_manager = OrderManager(self.stock_position_dic)

        self.quote_manager = QuoteManager()

        self.cumPNL = 0

    def recv_market(self, market_data):
        # print("recv_market callback:", market_data.symbol, 
        # market_data.market_time, market_data.high_price, 
        # market_data.pre_close_price, self.market_count)
        # 股票的策略不存在,初始化
        if market_data.symbol not in self.stock_position_dic:
            self.stock_position_dic[market_data.symbol] = Position()

        # 这只股票的仓位信息
        stock_position = self.stock_position_dic[market_data.symbol]
        # update market quotes
        self.quote_manager.update_table(market_data.symbol, market_data)
        # 运算策略
        self.strategy_instance.do_strategy(stock_position, self.order_manager, market_data, self.quote_manager)

    def recv_order_deal(self, deal_info):
        self.order_manager.recv_order_deal(deal_info)

    def reset(self):
        # 股票 -> 仓位
        self.stock_position_dic.clear()


    def addPNL(self, pnl):
        self.cumPNL + pnl
Esempio n. 12
0
    def __init__(self, exchange):
        self.exchange = exchange
        self.orderManager = OrderManager()
        self.logger.info("Initiate Price Arbitrage Algo")
        self._buildFxTree() # build fx tree for all possible conversions
        # build list of leaves
        root = self.tree.root  # get root
        w = Walker()  # tree walker
        # unwrap nested tuple returned by Walker to a flat list of FXPair
        def unwrapWalkerToFlatList(x):
            if isinstance(x, tuple):
                if len(x) == 0: return []
                s = []
                for t in x:
                    s.extend(unwrapWalkerToFlatList(t))
                return s
            else:
                if x.getFXPair() is None: return [] # skip root element
                else: return [x.getFXPair()]

        self.conversion_paths = {} # all conversion paths for the pair <pair: [pair1, pair2...]>
        # build list of all conversion paths
        for k in FXNode.treeNodesWithSamePair.keys():  # iterate all pairs
            alternative_list = FXNode.treeNodesWithSamePair[k]  # get list of leaves representing same pair but with different conversion path
            paths = []
            for c in alternative_list:  # iterate all leaves (same pair but different paths)
                if not c.is_leaf:
                    continue  # iterate only leaves
                path = unwrapWalkerToFlatList(w.walk(root, c))  # get path from root to this leaf
                paths.append(path) # list of lists

            if not k in self.conversion_paths.keys():
                self.conversion_paths[k] = list(paths)
            else:
                self.conversion_paths[k].append(list(paths))

        # set event triggers
        self.exchange.setEventHandler(tradeHandler=self.updateTradeHandler, orderHandler=self.updateOrderHandler)
Esempio n. 13
0
    def __init__(self, *args, **kwargs):
        super(TestOrderManager, self).__init__(*args, **kwargs)
        self.server = app.test_client()
        self.order_manager = OrderManager(self.server)
        self.test_data_key = "1"
        self.test_data = {"Toppings": "beef", "Sizes": "Large"}
        self.test_data_key2 = "2"
        self.test_data2 = {"Toppings": "Chicken", "Sizes": "Small"}
        self.test_data_key3 = "3"
        self.test_data3 = {"Toppings": "Fish", "Sizes": "Medium"}

        #reset what is on the test_client first due to other test
        r = self.server.get(self.order_manager._URL).get_json()
        for k in r.keys():
            self.server.delete(self.order_manager._URL, json=k)

        #initialize the server and push the test_data first
        #use dumps because it is more consistent with the ordermanager adding method
        self.server.post(self.order_manager._URL,
                         json={self.test_data_key: json.dumps(self.test_data)})
        self.server.post(
            self.order_manager._URL,
            json={self.test_data_key2: json.dumps(self.test_data2)})
Esempio n. 14
0
def main():
    lp_2_gateway = deque()
    ob_2_ts = deque()
    ts_2_om = deque()
    om_2_ts = deque()
    gw_2_om = deque()
    om_2_gw = deque()

    lp = LiquidityProvider(lp_2_gateway)
    ob = OrderBook(lp_2_gateway, ob_2_ts)
    ts = TradingStrategy(ob_2_ts, ts_2_om, om_2_ts)
    ms = MarketSimulator(om_2_gw, gw_2_om)
    om = OrderManager(ts_2_om, om_2_ts, om_2_gw, gw_2_om)

    lp.read_tick_data_from_data_source()

    while len(lp_2_gateway) > 0:
        ob.handle_order_from_gateway()
        ts.handle_input_from_bb()
        om.handle_input_from_ts()
        ms.handle_order_from_gw()
        om.handle_input_from_market()
        ts.handle_response_from_om()
        lp.read_tick_data_from_data_source()
Esempio n. 15
0
#COMMISSION      = .0                        # Cost in dollars per share traded
#COMMISSION_MIN  = .0                        # Minimum cost in dollars per stock traded
#COMMISSION_MAX  = .0                        # Maximum cost in percent of trade value
#SLIPPAGE        = .0                        # Average slippage in price due to market volatility

# Create QuoteManager object
quote_manager = QuoteManager(DB_FILEPATH)

# Create AccountManager object
my_account = AccountManager(START_BALANCE, MARGIN_PERCENT, quote_manager)

# Create OrderManager object
order_manager = OrderManager(quote_manager,
                             my_account,
                             slippage=SLIPPAGE,
                             commission_min=COMMISSION_MIN,
                             commission=COMMISSION,
                             commission_max=COMMISSION_MAX)

# Create an order_history DataFrame
order_history = {}

# Load signals data
signals = pd.read_csv(SIGNALS_PATH, index_col=0)
signal_dates = [date.replace('-', '_') for date in signals.index]

# Load GDX component symbols
gdx_symbols = pd.read_csv(GDX_CSV_PATH).symbol
gdx_symbols = gdx_symbols[gdx_symbols.isin(signals.columns)]

# Skip days until START_DAY is found
Esempio n. 16
0
class OrderManagerTest(TestCase):
    def setUp(self):
        self.order_manager = OrderManager()

        self.person_1 = new_person(
                {'username': '******', 'name': 'Name1', 'surname': 'Surname1', 'password': '******',
                 'passwordRetype': 'test123', 'email': '*****@*****.**'})

        self.person_1.number_of_stocks = 5
        self.person_1.save()

        self.person_2 = new_person(
                {'username': '******', 'name': 'Name2', 'surname': 'Surname2', 'password': '******',
                 'passwordRetype': 'test123', 'email': '*****@*****.**'})

        self.person_3 = new_person(
                {'username': '******', 'name': 'Name3', 'surname': 'Surname3', 'password': '******',
                 'passwordRetype': 'test123', 'email': '*****@*****.**'})

        self.bidding_round = BiddingRound.objects.create(is_active=True)

        stock_order_1 = StockOrder()
        stock_order_1.owner = self.person_1
        stock_order_1.order_type = BUY
        stock_order_1.order_price_per_share = 8.5
        stock_order_1.order_amount_of_shares = 10
        stock_order_1.bidding_round = self.bidding_round

        stock_order_2 = StockOrder()
        stock_order_2.owner = self.person_1
        stock_order_2.order_type = BUY
        stock_order_2.order_price_per_share = 7.5
        stock_order_2.order_amount_of_shares = 5
        stock_order_2.bidding_round = self.bidding_round

        stock_order_3 = StockOrder()
        stock_order_3.owner = self.person_1
        stock_order_3.order_type = BUY
        stock_order_3.order_price_per_share = 6.5
        stock_order_3.order_amount_of_shares = 15
        stock_order_3.bidding_round = self.bidding_round

        stock_order_arch = StockOrder()
        stock_order_arch.owner = self.person_1
        stock_order_arch.order_type = SELL
        stock_order_arch.order_price_per_share = 5
        stock_order_arch.order_amount_of_shares = 100
        stock_order_arch.bidding_round = self.bidding_round
        stock_order_arch.is_archived = True

        self.order_1_person_1 = self.order_manager.place_order(stock_order_1)
        self.order_2_person_1 = self.order_manager.place_order(stock_order_2)
        self.order_3_person_1 = self.order_manager.place_order(stock_order_3)
        self.order_archived_person_1 = create_stock_order(stock_order_arch)

        self.order_1_person_2 = StockOrder.objects.create(owner=self.person_2)
        self.order_2_person_2 = StockOrder.objects.create(owner=self.person_2)

        self.order_1_person_3 = StockOrder.objects.create(owner=self.person_2)

    def test_can_place_order(self):
        """
        checks if user can place order:
          * bidding period is active (first, second and third complete week of october)
              - first bidding round for third party and staff
              - second bidding round for staff
              - third bidding round for moderator
          * user has not exceeded his maximal bidding order number
          * total of non-archived SELL orders incl this one does not exceeded
            persons number_of_stocks (exp moderator_person)
        returns error message, None otherwise
        """
        self.person_1.number_of_orders_max = 6
        self.person_1.number_of_stocks = 50

        stock_order = StockOrder()
        stock_order.order_amount_of_shares = 10
        stock_order.owner = self.person_1
        stock_order.order_type = SELL
        # create_stock_order(stock_order)

        # =================================================================
        # test: NoBiddingRoundException
        # =================================================================

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('NoBiddingRoundException expected')
        except NoBiddingRoundException:
            pass

        # create bidding round
        bidding_round = BiddingRound.objects.create(is_active=True)
        stock_order.bidding_round = bidding_round

        # valid order
        self.assertIsNone(self.order_manager.can_place_order(self.person_1, stock_order))

        # =================================================================
        # test: BiddingRoundNotActiveException
        # =================================================================

        bidding_round.is_active = False

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('BiddingRoundNotActiveException expected')
        except BiddingRoundNotActiveException:
            pass

        bidding_round.is_active = True
        self.assertIsNone(self.order_manager.can_place_order(self.person_1, stock_order))

        # =================================================================
        # test: UserTypeException
        # =================================================================

        bidding_round.round_type = bidding_constants.STAFF_ROUND

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('UserTypeException expected')
        except UserTypeException:
            pass

        self.person_1.user_type = person_constants.STAFF
        self.assertIsNone(self.order_manager.can_place_order(self.person_1, stock_order))

        bidding_round.round_type = bidding_constants.MODERATOR_ROUND

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('UserTypeException expected')
        except UserTypeException:
            pass

        self.person_1.user_type = person_constants.MODERATOR
        self.assertIsNone(self.order_manager.can_place_order(self.person_1, stock_order))

        self.person_1.user_type = person_constants.THIRD_PARTY

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('UserTypeException expected')
        except UserTypeException:
            pass

        bidding_round.round_type = bidding_constants.THIRD_PARTY_ROUND
        self.assertIsNone(self.order_manager.can_place_order(self.person_1, stock_order))

        # =================================================================
        # test: ExceedMaxSellSharesException
        # =================================================================

        stock_order.order_amount_of_shares = 51

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('ExceedMaxSellSharesException expected')
        except ExceedMaxSellSharesException:
            pass

        stock_order.order_amount_of_shares = 49

        self.assertIsNone(self.order_manager.can_place_order(self.person_1, stock_order))

        stock_order_4 = StockOrder()
        stock_order_4.owner = self.person_1
        stock_order_4.order_type = SELL
        stock_order_4.order_price_per_share = 5.5
        stock_order_4.bidding_round = self.bidding_round
        stock_order_4.order_amount_of_shares = 1

        self.order_manager.place_order(stock_order_4)

        self.assertIsNone(self.order_manager.can_place_order(self.person_1, stock_order))

        stock_order_5 = StockOrder()
        stock_order_5.owner = self.person_1
        stock_order_5.order_type = SELL
        stock_order_5.bidding_round = self.bidding_round
        stock_order_5.order_amount_of_shares = 1
        stock_order_5.order_price_per_share = 8.5

        self.order_manager.place_order(stock_order_5)

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('ExceedMaxSellSharesException expected')
        except ExceedMaxSellSharesException:
            pass

        # =================================================================
        # test: ExceedMaxOrderException
        # =================================================================

        stock_order.order_type = BUY

        stock_order_5 = StockOrder()
        stock_order_5.owner = self.person_1
        stock_order_5.order_type = BUY
        stock_order_5.bidding_round = self.bidding_round
        stock_order_5.order_amount_of_shares = 50
        stock_order_5.order_price_per_share = 6.5

        self.order_manager.place_order(stock_order_5)

        try:
            self.order_manager.can_place_order(self.person_1, stock_order)
            raise AssertionError('ExceedMaxOrderException expected')
        except ExceedMaxOrderException:
            pass

    def test_is_valid_order(self):
        """
        checks if stock order is valid:
          * order must have a order_type BUY or SELL
          * order must have order_price_per_share (float)
          * order must have order_amount_of_shares (int)
          * order must have owner (Person)
        returns error message, None otherwise
        """
        stock_order = StockOrder()
        stock_order.order_type = BUY
        stock_order.order_price_per_share = 5.5
        stock_order.order_amount_of_shares = 10
        stock_order.bidding_round = self.bidding_round

        # =================================================================
        # test: OwnerNotFoundException
        # =================================================================

        try:
            self.order_manager.is_valid_order(stock_order)
            raise AssertionError('OwnerNotFoundException expected')
        except OwnerNotFoundException:
            pass

        stock_order.owner = self.person_1

        self.assertIsNone(self.order_manager.is_valid_order(stock_order))

        # =================================================================
        # test: InvalidOrderTypeException
        # =================================================================

        stock_order.order_type = UNDEFINED

        try:
            self.order_manager.is_valid_order(stock_order)
            raise AssertionError('InvalidOrderTypeException expected')
        except InvalidOrderTypeException:
            pass

        stock_order.order_type = SELL
        self.assertIsNone(self.order_manager.is_valid_order(stock_order))

        # =================================================================
        # test: OrderPriceTypeException
        # =================================================================

        stock_order.order_price_per_share = "0.01"

        try:
            self.order_manager.is_valid_order(stock_order)
            raise AssertionError('OrderPriceTypeException expected')
        except OrderPriceTypeException:
            pass

        stock_order.order_price_per_share = 123456789012345678901234567890

        try:
            self.order_manager.is_valid_order(stock_order)
            raise AssertionError('OrderPriceTypeException expected')
        except OrderPriceTypeException:
            pass

        stock_order.order_price_per_share = 2312.34
        self.assertIsNone(self.order_manager.is_valid_order(stock_order))

        # =================================================================
        # test: OrderShareAmountException
        # =================================================================

        stock_order.order_amount_of_shares = "0.01"

        try:
            self.order_manager.is_valid_order(stock_order)
            raise AssertionError('OrderShareAmountException expected')
        except OrderShareAmountException:
            pass

        stock_order.order_amount_of_shares = 123456789012345678901234567890

        try:
            self.order_manager.is_valid_order(stock_order)
            raise AssertionError('OrderShareAmountException expected')
        except OrderShareAmountException:
            pass

        stock_order.order_amount_of_shares = 2312.34

        try:
            self.order_manager.is_valid_order(stock_order)
            raise AssertionError('OrderShareAmountException expected')
        except OrderShareAmountException:
            pass

        stock_order.order_amount_of_shares = 23120
        self.assertIsNone(self.order_manager.is_valid_order(stock_order))

    def test_place_order(self):
        stock_order_4 = StockOrder()
        stock_order_4.owner = self.person_1
        stock_order_4.order_type = SELL
        stock_order_4.bidding_round = self.bidding_round
        stock_order_4.is_archived = True
        stock_order_4.order_amount_of_shares = 5
        stock_order_4.order_definite_number_of_shares = 4
        stock_order_4.order_definite_price = 12.5321
        stock_order_4.order_price_per_share = 24.5321
        stock_order_4.order_result = ASSIGNED_PARTIAL
        stock_order_4.order_status = USER_ACCEPTED

        stock_order_created = self.order_manager.place_order(stock_order_4)

        # check values
        self.is_equal_stock_order(stock_order_4, stock_order_created)
        self.assertEquals(len(stock_order_created.encrypted_order_id), 32)

        # =================================================================
        # test: PlaceOrderException
        # =================================================================

        stock_order_4.order_amount_of_shares = 10

        try:
            self.order_manager.place_order(stock_order_4)
            raise AssertionError('PlaceOrderException expected')
        except PlaceOrderException:
            pass

    def test_accept_oder(self):

        # =================================================================
        # test: increase / decrease stock numbers and status
        # =================================================================

        self.assertEquals(self.person_1.number_of_orders_accepted, 0)
        self.assertEquals(self.person_1.number_of_orders_pending, 3)

        encrypted_order_id = self.order_1_person_1.encrypted_order_id
        stock_order = StockOrder.objects.get(owner=self.person_1, encrypted_order_id=encrypted_order_id)

        self.assertEquals(stock_order.order_status, NEW)

        self.order_manager.accept_oder(self.person_1, encrypted_order_id)

        self.assertEquals(self.person_1.number_of_orders_accepted, 1)
        self.assertEquals(self.person_1.number_of_orders_pending, 2)

        stock_order = StockOrder.objects.get(owner=self.person_1, encrypted_order_id=encrypted_order_id)

        self.assertEquals(stock_order.order_status, USER_ACCEPTED)

        # =================================================================
        # test: AlreadyAcceptedException
        # =================================================================

        try:
            self.order_manager.accept_oder(self.person_1, encrypted_order_id)
            raise AssertionError('AlreadyAcceptedException expected')
        except AlreadyAcceptedException:
            pass

        # second time accept_oder should have no consequence

        self.assertEquals(self.person_1.number_of_orders_accepted, 1)
        self.assertEquals(self.person_1.number_of_orders_pending, 2)

        stock_order = StockOrder.objects.get(owner=self.person_1, encrypted_order_id=encrypted_order_id)

        self.assertEquals(stock_order.order_status, USER_ACCEPTED)

        # =================================================================
        # test: OrderNotFoundException
        # =================================================================

        try:
            self.order_manager.accept_oder(self.person_1, "XXX")
            raise AssertionError('OrderNotFoundException expected')
        except OrderNotFoundException:
            pass

        try:
            self.order_manager.accept_oder(self.person_2, encrypted_order_id)
            raise AssertionError('OrderNotFoundException expected')
        except OrderNotFoundException:
            pass

        # =================================================================
        # test: OrderIsArchivedException
        # =================================================================

        encrypted_order_id = self.order_archived_person_1.encrypted_order_id
        stock_order = StockOrder.objects.get(owner=self.person_1, encrypted_order_id=encrypted_order_id)

        try:
            self.order_manager.accept_oder(self.person_1, encrypted_order_id)
            raise AssertionError('OrderIsArchivedException expected')
        except OrderIsArchivedException:
            pass

        self.is_equal_stock_order(self.order_archived_person_1, stock_order)

    def is_equal_stock_order(self, real, expected):
        self.assertEquals(real.order_amount_of_shares, expected.order_amount_of_shares)
        self.assertEquals(real.order_price_per_share, expected.order_price_per_share)
        self.assertEquals(real.order_definite_number_of_shares, expected.order_definite_number_of_shares)
        self.assertEquals(real.order_definite_price, expected.order_definite_price)
        self.assertEquals(real.is_archived, expected.is_archived)
        self.assertEquals(real.owner, expected.owner)
        self.assertEquals(real.order_type, expected.order_type)
        self.assertEquals(real.order_result, expected.order_result)
        self.assertEquals(real.order_status, expected.order_status)
Esempio n. 17
0
class PriceArbitrage:
    # class variables
    logger = logging.getLogger('price arbitrage')

    def __init__(self, exchange):
        self.exchange = exchange
        self.orderManager = OrderManager()
        self.logger.info("Initiate Price Arbitrage Algo")
        self._buildFxTree() # build fx tree for all possible conversions
        # build list of leaves
        root = self.tree.root  # get root
        w = Walker()  # tree walker
        # unwrap nested tuple returned by Walker to a flat list of FXPair
        def unwrapWalkerToFlatList(x):
            if isinstance(x, tuple):
                if len(x) == 0: return []
                s = []
                for t in x:
                    s.extend(unwrapWalkerToFlatList(t))
                return s
            else:
                if x.getFXPair() is None: return [] # skip root element
                else: return [x.getFXPair()]

        self.conversion_paths = {} # all conversion paths for the pair <pair: [pair1, pair2...]>
        # build list of all conversion paths
        for k in FXNode.treeNodesWithSamePair.keys():  # iterate all pairs
            alternative_list = FXNode.treeNodesWithSamePair[k]  # get list of leaves representing same pair but with different conversion path
            paths = []
            for c in alternative_list:  # iterate all leaves (same pair but different paths)
                if not c.is_leaf:
                    continue  # iterate only leaves
                path = unwrapWalkerToFlatList(w.walk(root, c))  # get path from root to this leaf
                paths.append(path) # list of lists

            if not k in self.conversion_paths.keys():
                self.conversion_paths[k] = list(paths)
            else:
                self.conversion_paths[k].append(list(paths))

        # set event triggers
        self.exchange.setEventHandler(tradeHandler=self.updateTradeHandler, orderHandler=self.updateOrderHandler)

    #bild tree representing all possible fx conversion rates
    def _buildFxTree(self):
        # build all fx conversion paths
        pairs = self.exchange.getFxPairs()
        #self.logger.info(pairs)
        # Generate tree for all possible conversion rate (recursive)
        def generateFxTree(tree, pairs):
            # climb up the tree (recursive) to check if pair is above the node to prevent loops
            def isNodeInTheTree(c, tree):  # tree is the terminal leaf
                a = c.getPairCode()
                b = tree.getPairCode()
                if a == b:
                    return True
                else:
                    if tree.parent is not None:
                        return isNodeInTheTree(c, tree.parent)
                    else:
                        return False  # reached the root
            for c in pairs:
                if isNodeInTheTree(c, tree):
                    continue
                else:
                    base = tree.getBase()
                    quote = c.getQuote()
                    if base != quote and base is not None and quote is not None:
                        continue
                    else:
                        fx_node = FXNode(c.getPairCode(), c, parent=tree)
                        generateFxTree(fx_node, pairs)
            return tree

        # generate currency exchange options
        root = FXNode("root")
        self.tree = generateFxTree(root, pairs)

        #print(RenderTree(root))
        print("----******-----")
        for pre, _, node in RenderTree(root):
            treestr = u"%s%s" % (pre, node.name)
            print(treestr.ljust(8))

        self.logger.info("-------FX pairs------------")
        #self.logger.info(pairs)

    # update algo for data change
    def updateTradeHandler(self, currencyPair):
        self.logger.info("Process trade update for pair %s" % (currencyPair.getPairCode()))


    def updateOrderHandler(self, pair):
        self.logger.info("Process ORDER update for pair %s" % (pair.getPairCode()))
        nodes = FXNode.treeNodesWithSamePair[pair]
        visited_leaves = []
        # check all paths (terminal leaves) which include this pair
        for n in nodes:
            descendants = n.descendants + (n,)
            for r in descendants:
                if not r.is_leaf: continue
                p = r.getFXPair()
                if p in visited_leaves: continue
                visited_leaves.append(p)
                if not self.is_book_data_available_in_the_tree(r):
                    continue
                self.checkArbitrageOpportunity(p, pair)

    # check if book data is available for all nodes in the route to this node
    def is_book_data_available_in_the_tree(self, node):
        return True

    # maximum conversion path, default is long / ask
    def estimateLongPathMaxThroughoutput(self, path,  startQuoteValue = None, bid=False):
        startValue = path[0].getMaxBookQuote(bid) if startQuoteValue is None else startQuoteValue
        b = startValue
        for p in path:
            b = p.limitedConvertQnt2Base(b, bid)
        lastPair = path[- 1]
        res = {
            'result_val': b,
            'result_currency': lastPair.getBase(),
            'start_val': startValue,
            'start_currency': path[0].getQuote()
        }
        return res #(b, lastPair.getBase(), startValue)  # in base currency of the final leaf

    # Estimate short route, path is given from root to leaf
    def estimateShortPathMaxThroughoutput(self, path, startBaseValue = None, ask=False):
        startValue = path[-1].getMaxBookBase() if startBaseValue is None else startBaseValue
        q = startValue
        for p in reversed(path):
            q = p.limitedConvertBase2Qnt(q, ask)
        lastPair = path[0]  # reverse order
        res = {
            'result_val' : q,
            'result_currency' : lastPair.getQuote(),
            'start_val' : startValue,
            'start_currency' : path[-1].getBase()
         }
        return res #(q, lastPair.getQuote(), startValue)  # in base quote of the final leaf

    # estimate maximum possible value of the arbitrage transaction
    def estimateMaximumThroughOutput(self, pair, longPath, shortPath):
        # first time estimate max throughoutput
        a = self.estimateLongPathMaxThroughoutput(longPath, bid = False)  # root -> leaf, use inverse mode (True) to get actual max initial value
        b = self.estimateShortPathMaxThroughoutput(shortPath, a['result_val'], ask = False)  # leaf -> root
        return b

    # Check if bid and ask data is available for all pairs in the path
    def bookDataAvailableInPath(self, path):
        a = True
        for x in path:
            a = a and x.isBidAvailable() and x.isAskAvailable()
            if not a:
                break
        return a

    def checkArbitrageOpportunity(self, pair, updatedPair):
        arbitrageDescriptor = {
            "long" : {
                "return" : 0.0,
                "path": [],
                'max_start_val' : 0.0,
                's1'  : None,
                's2' : None
            },
            "short" : {
                "return" : 0,
                "path" : [],
                's1' : None,
                's2'    : None
            },
            'max_transaction' : {
                'currency' : '',
                'val' : 0.0
            }
        }

        for path in self.conversion_paths[pair]:
            #for p in path: # iterate all leaves (each leaf is the same pair but different conversion path)
            #long leg
            if not updatedPair in path or not self.bookDataAvailableInPath(path):
                continue
            longMaxVal = self.estimateLongPathMaxThroughoutput(path) # estimate max value
            if longMaxVal['result_val'] == 0:
                continue
            # convert half (to make sure it goes through) of the max value into original currency using ask book
            s = self.estimateShortPathMaxThroughoutput(path, longMaxVal['result_val'] / 2, ask = True)
            #startLongValue = s ['result_val']
            #longVal = self.estimateLongPathMaxThroughoutput(path, startLongValue) # put through half of the max possible value
            #long_ret = longVal['result_val'] / longVal['start_val'] # normalize: 1 Quote currency -> x Base currency, then x is a
            if s['result_val'] == 0:
                continue
            long_ret = s['start_val'] / s['result_val']
            ex = self.exchange.convert_amt(longMaxVal['start_currency'], 'BTC', 1.0)
            if ex == 0:
                self.logger.info('cant conver from %s to BTC' % longMaxVal['start_currency'] )
                continue
            long_ret /= ex # 1 btc - > xx base currency, so all conversions start with 1 btc and thus we can compare then
            if long_ret > arbitrageDescriptor['long']['return']:
                arbitrageDescriptor['long']['return'] = long_ret
                arbitrageDescriptor['long']['path'] = path
                arbitrageDescriptor['long']['s1'] = longMaxVal
                arbitrageDescriptor['long']['s2'] = s
                arbitrageDescriptor['long']['max_start_val'] = s['result_val']*2
                arbitrageDescriptor['max_transaction']['val'] = s['start_val']*2 # in base currency
                arbitrageDescriptor['max_transaction']['currency'] = s['start_currency']
            # short leg
            shortMaxVal = self.estimateShortPathMaxThroughoutput(path)
            if shortMaxVal['result_val'] == 0:
                continue
            # convert hald of the max value into the original currency
            s1 = self.estimateLongPathMaxThroughoutput(path, shortMaxVal['result_val'] / 2, bid = True)
            #startShortValue = self.exchange.convert_amt(shortMaxVal[1], path[-1].getBase(), shortMaxVal[0])
            #startShortValue = s['result_val']
            #shortVal = self.estimateShortPathMaxThroughoutput(path, startShortValue)
            #short_ret = self.exchange.convert_amt(shortVal['result_currency'], 'BTC', shortVal['result_val'])
            #short_ret = shortVal['result_val'] / shortVal ['start_val'] # normalize
            short_ret = s1['start_val'] / s1['result_val']
            short_ret = self.exchange.convert_amt(s1['start_currency'],'BTC', short_ret)
            if short_ret > arbitrageDescriptor['short']['return']:
                arbitrageDescriptor['short']['return'] = short_ret
                arbitrageDescriptor['short']['path'] = path
                arbitrageDescriptor['short']['s1'] = shortMaxVal
                arbitrageDescriptor['short']['s2'] = s1
        # calculate arbitrage return
        ret = arbitrageDescriptor['long']['return'] * arbitrageDescriptor['short']['return'] - 1
        if ret == - 1:
            return
        print("Arbitrage %s return: %.4f" % (pair.getPairCode(), ret))
        if ret > 0:
            curr = arbitrageDescriptor['max_transaction']['currency']
            currVal = arbitrageDescriptor['max_transaction']['val'] * ret
            btc = 0 #self.exchange.convert_amt(curr,'BTC', currVal)
            print('**** ARBITRAGE OPPORTUNITY. Earn %.4f %s (%.4f BTC)' % (currVal, curr, btc))
            self.debug_arbitrage(pair, arbitrageDescriptor) # arbitrage opportunity


    # recalculate arbitrage for a given pair
    def checkArbitrageOpportunity_old(self, pair):
        arbitrageDescriptor = {
            "long" : {
                "val" : 0,
                "path": []
            },
            "short" : {
                "val" : 0,
                'btc_val' : 0,
                "path" : []
            }
        }
        for path in self.conversion_paths[pair]:
            # calculate conversion values: we begin with 1 BTC on a long path and 1 unit of local currency on a short path
            firstPair = path[0]  # first element should be the first pair (zero/0 element is a fake "root" element)
            # start with value of 1 btc in local currency
            longVal = float(self.exchange.convert_amt('BTC', firstPair.getQuote(), 1.0, _bid = False))  # use ASK for algo initialization
            if longVal == 0:
                continue
            shortVal = 1.0
            for p in path: # iterate all leaves (each leaf is the same pair but different conversion path)
                # estimate long value: quote -> base conversion which is considered long
                ex_rate1 = float(p.get_average_ask_price_for_quote_amt(longVal))  # at what price I can buy 1 unit of base currency
                if ex_rate1 == 0:
                    break # no data - skip path
                longVal = longVal / ex_rate1  # convert quote currency to base currency
                # estimate short value ( base -> quote)
                ex_rate2 = float(p.get_average_bid_price_for_base_amt(1.0) ) # at what price I can sell 1 unit of base currency and get quote curreny
                if ex_rate2 == 0:
                    break # no data - skip path
                shortVal = shortVal * ex_rate2
            # keep track of max
            # all longVal are expressed in terms of base / local currency of the pair, so we can compare them
            if longVal > arbitrageDescriptor['long']['val']:
                arbitrageDescriptor['long']['val'] = longVal
                arbitrageDescriptor['long']['path'] = path
            # on the other hand, all shortVal are expressed in terms of quote currency of the path root which are different
            # so we need to convert shortVal to btc in order to compare them
            shortVal_btc = self.exchange.convert_amt(firstPair.getQuote(), 'BTC', shortVal, _bid = False)  # buy btc
            if shortVal_btc == 0:
                continue  # no data
            if  shortVal_btc > arbitrageDescriptor['short']['btc_val']:
                arbitrageDescriptor['short']['btc_val'] = shortVal_btc
                arbitrageDescriptor['short']['path'] = path
                arbitrageDescriptor['short']['val'] = shortVal

        arbitrageDescriptor['arb_return'] = arbitrageDescriptor['long']['val'] * arbitrageDescriptor['short']['btc_val'] - 1
        #self.estimateMaximumThroughOutput(pair)
        a = pair.getPairCode()
        b = arbitrageDescriptor['arb_return']
        self.logger.info("Arbitrage %s return: %.2f" % (a,b) )
        if arbitrageDescriptor['arb_return'] > 0:
            self.arbitrageHandler(pair, arbitrageDescriptor) # process arbitrage


    # Process arbitrage event
    def arbitrageHandler(self, pair, arbitrage):
        print(" ****** ARBITRAGE FOR THE PAIR %s " % pair.getPairCode())

        #firstPair = arbitrage['long']['path'][0]  # first element should be first pair (zero/0 element is a fake "root" element)
        # Estimate maximum possible value of the transaction on long-short path (expressed in terms of the last node of short path)
        (transaction_max_amt, arb_val_currency,x)  = self.estimateMaximumThroughOutput(pair, arbitrage['long']['path'], arbitrage['short']['path'])
        arb_max_profit = arbitrage['arb_return'] * transaction_max_amt # max possible arbitrage value
        #shortPath = arbitrage['short']['path']
        #arb_val_currency = shortPath[len(shortPath) - 1].getQuote() # currency in which arbitrage value is expressed
        # get btc value of arbitrage profit
        arbitrage['max_transaction'] = {'val':  transaction_max_amt,
                                        'currency' :  arb_val_currency }
        arb_max_profit_btc = self.exchange.convert_amt(arb_val_currency, 'BTC', arb_max_profit, _bid = False)  # buy BTC
        print('Arbitrage return: %f. Maximum transaction amt %f %s. Arbitrage profit %f %s (%f BTC)' % (arbitrage['arb_return'],
                                                                                        transaction_max_amt, arb_val_currency,
                                                                                        arb_max_profit, arb_val_currency,
                                                                                        arb_max_profit_btc  ))
        self.debug_arbitrage(pair, arbitrage)

        # execute arbitrage sequence
        self.execute_arbitrage(pair, arbitrage)


    def execute_arbitrage(self, pair, arbitrage):
        # long leg
        longPath = arbitrage['long']['path']
        firstPair = longPath[0]  # first element should be the first pair (zero/0 element is a fake "root" element)
        # start with value of 1 btc in local currency
        longVal = self.exchange.convert_amt(
            arbitrage['max_transaction']['currency'], firstPair.getQuote(), arbitrage['max_transaction']['val'],
            _bid=False)  # use ASK for algo initialization/
        for p in longPath:
            e = p.get_average_ask_price_for_quote_amt(longVal)
            longVal = longVal / e
            # create buy order
            o = Order(p, 'BUY', longVal, type = 'LIMIT', price = 0 )
            self.orderManager.execute_order(o)
            status = o.get_status()
            if status == 'OK': # IN_PROGRESS, COMPLETED, FAILED, PARTIALLY_COMPLETED
                pass
            elif status == 'CANCELED':
                pass
            elif status == 'FAILED':
                pass
            elif status == 'PARTIAL':
                pass



    def debug_arbitrage(self, pair, arbitrage):
        longPath = arbitrage['long']['path']
        firstPair = longPath[0]  # first element should be the first pair (zero/0 element is a fake "root" element)
        # start with value of 1 btc in local currency
        longVal =  arbitrage['long']['max_start_val']
        #self.exchange.convert_amt(arbitrage['max_transaction']['currency'], firstPair.getQuote(), arbitrage['max_transaction']['val'], _bid=False)  # use ASK for algo initialization/
        s= ""
        for p in longPath:
            l = longVal
            e = p.get_average_ask_price_for_quote_amt(longVal)
            s = str(longVal) + " " + p.getQuote() + " -> "
            longVal = longVal / e
            s += str(longVal) + " " + p.getBase() + "@" + str(e)
            print(s)
            print("Ask book: AverageAskPrie(%f)=%f" % (l, e))
            print(p.asks)

        shortPath = arbitrage['short']['path']
        print("**** SHORTING:")
        shortVal = longVal
        firstPair = shortPath[- 1]
        for index, p in enumerate(reversed(shortPath)):
            k = shortVal
            e = p.get_average_bid_price_for_base_amt(shortVal)
            s = str(shortVal) + " " + p.getBase() + " -> "
            shortVal = shortVal * e
            s += str(shortVal) + " " + p.getQuote() + "@" + str(e)
            print(s)
            print("Bid book: AverageBidPrie(%f)=%f" % (k, e))
            print(p.bids)
        shortVal_original = self.exchange.convert_amt(firstPair.getQuote(), longPath[0].getQuote(), shortVal, _bid=False)  # buy btc
        print(str(shortVal) + " " + firstPair.getQuote()+ "->" + str(shortVal_original) + longPath[0].getQuote() + "@" + str(e) )
        a = 5
Esempio n. 18
0
    def test_init(self):
        self.x = OrderManager()

        assert type(self.x._orders) == dict
        assert self.x._up_to_id == 0
Esempio n. 19
0
class Test:
    def test_init(self):
        self.x = OrderManager()

        assert type(self.x._orders) == dict
        assert self.x._up_to_id == 0

    def test_setters(self):
        self.x = OrderManager()

        id1 = self.x.create_new_order()

        assert len(self.x.orders) == 1
        assert type(self.x.orders[0]) == Order
        assert type(self.x.get_order_by_id(id1)) == Order

        id2 = self.x.create_new_order()

        assert len(self.x.orders) == 2

    def test_checker(self):
        #we expect the first order created to have an id of 0
        self.x = OrderManager()

        assert self.x.id_exists('0') == False

        self.x.create_new_order()

        assert self.x.id_exists('0') == True

    def test_invalid_cases(self):
        self.x = OrderManager()

        with pytest.raises(TypeError):
            self.x.get_order_by_id('1.1')

        with pytest.raises(TypeError):
            self.x.get_order_by_id(1.1)

        with pytest.raises(KeyError):
            self.x.get_order_by_id('1')

        assert self.x.id_exists('a') == False
Esempio n. 20
0
 def setUp(self):
     self.order_manager = OrderManager()
Esempio n. 21
0
                # process_order(signal_dict)
                # data.db_append_history(signal_dict)
                # print('Signal "%s" zpracovan s nasledujicimi parametry:' % signal_dict['puvodni_zprava'])
                # print("Operace: ", signal_dict['operace'])
                # print("Mnozstvi:", int(signal_dict['mnozstvi'])*int(signal_dict['nasobeni']))
                # print("Cena (signal/skutecnost): %d/%d" % (signal_dict['cena'], signal_dict['skutecna_cena']))
                # print("Vysledek: %s - ID: %d" % (signal_dict['vysledek'], signal_dict['order_id']))
        except Exception as loop_error:
            tg_client.send_message("me", "CHYBA: %s" % loop_error)
            raise


if __name__ == "__main__":
    print("Spoustim pripojeni k API")
    try:
        tg_client, tws_client = get_clients()

        orderman = OrderManager(tws_client, tws_queue)

        tg_client.start()
        # TODO: Vytvorit sjednocenou inicializacni metodu obsahujici server clock a ID printout
        while tws_client.is_error():
            print(tws_client.get_error())
        tws_client.refresh_next_id()
    except Exception as e:
        print("[CHYBA!]: Nepovedlo se pripojit k TWS nebo Telegramu")
        traceback.print_exc()

    the_loop()
Esempio n. 22
0
 def test_get_signature(self):
     om = OrderManager('btcusd')
     self.assertDictEqual(om._OrderManager__get_signature(),
                          {'key': 'abcdefghijklmnopqrstuvwxyz123456',
                           'signature': '7728462B38496C189AFAED03A0C51FAB7D2358FA0FE1995C976FF755E794489D',
                           'nonce': '1563871382'})
Esempio n. 23
0
def main():

    parser = argparse.ArgumentParser()
    parser.add_argument('market',
                        type=str,
                        choices=constants.MARKETS,
                        help='currency pair - btcusd, ltcusd, etc')
    market = (parser.parse_args()).market

    logging.info('the market {} was chosen'.format(market))

    ts = TradingStrategy(market)
    om = OrderManager(market)
    md = MarketDataInterface(market)

    running = True

    while running:
        action = ts.get_final_strategy()
        price = Decimal(str((md.get_ticker_data(False))[3]))

        time = datetime.datetime.now()
        if abs((time - datetime.datetime.strptime(
                md.get_ticker_data(False)[2],
                '%Y-%m-%d %H:%M:%S')).seconds) > 600:
            logging.error('database is out of date, exiting')
            running = False

        balance = om.get_balance()
        if None in balance.values():
            logging.info('failed to get account balance')

        try:
            if action['action'] == 'buy':
                amount = (Decimal(str(action['risk'])) *
                          Decimal(balance['second_available']) / price)
            elif action['action'] == 'sell':
                amount = (Decimal(str(action['risk'])) *
                          Decimal(balance['available']))
            else:
                amount = Decimal('0')
        except TypeError:
            logging.exception('could not determine amount')
            amount = Decimal('0')

        if action['action'] in ['buy', 'sell']:
            if market[-3:] in ['usd', 'eur']:
                if (amount * price) < constants.EUR_USD_MIN_TRANSACTION_SIZE:
                    action['action'] = 'wait'
                    amount = Decimal('0')
                    logging.info(
                        'do not have minimum amount ({}) to trade'.format(
                            constants.EUR_USD_MIN_TRANSACTION_SIZE))
                price = price.quantize(Decimal('.01'))

                if market[:3] in ['xrp', 'usd', 'eur']:
                    amount = amount.quantize(Decimal('.00001'))
                else:
                    amount = amount.quantize(Decimal('.00000001'))

            elif market[-3:] == 'btc':
                if (amount * price) < constants.BTC_MIN_TRANSACTION_SIZE:
                    action['action'] = 'wait'
                    amount = Decimal('0')
                    logging.info(
                        'do not have minimum amount ({}) to trade'.format(
                            constants.BTC_MIN_TRANSACTION_SIZE))
                price = price.quantize(Decimal('.00000001'))

        if action['action'] == 'buy':
            sleep(1)
            order_id = om.buy(price=price, amount=amount)
            if order_id:
                logging.info(
                    'successfully bought {amount}{currency_one} at {price}{currency_two} each'
                    .format(amount=amount,
                            currency_one=market[:3],
                            price=price,
                            currency_two=market[-3:]))

        elif action['action'] == 'sell':
            sleep(1)
            order_id = om.sell(price=price, amount=amount)
            if order_id:
                logging.info(
                    'successfully sold {amount}{currency_one} at {price}{currency_two} each'
                    .format(amount=amount,
                            currency_one=market[:3],
                            price=price,
                            currency_two=market[-3:]))

        elif action['action'] == 'wait':
            logging.info('waiting {}s, did not trade'.format(
                settings.MAIN_TIMER))

        else:
            running = False
            logging.error(
                'exiting trader - unsupported action (supported actions: buy, sell, wait), {}'
                .format(action))

        sleep(1)
        open_orders = om.get_open_orders()
        if open_orders:
            for order in open_orders:
                time = datetime.datetime.now().timestamp()
                sleep(1)
                if datetime.datetime.strptime(
                        order['datetime'],
                        '%Y-%m-%d %H:%M:%S').timestamp() < time - 21600:
                    om.cancel_order(order['id'])

        sleep(settings.MAIN_TIMER)
        logging.info('waited {}s to trade again'.format(settings.MAIN_TIMER))
Esempio n. 24
0
class TestOrderManager(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        super(TestOrderManager, self).__init__(*args, **kwargs)
        self.server = app.test_client()
        self.order_manager = OrderManager(self.server)
        self.test_data_key = "1"
        self.test_data = {"Toppings": "beef", "Sizes": "Large"}
        self.test_data_key2 = "2"
        self.test_data2 = {"Toppings": "Chicken", "Sizes": "Small"}
        self.test_data_key3 = "3"
        self.test_data3 = {"Toppings": "Fish", "Sizes": "Medium"}

        #reset what is on the test_client first due to other test
        r = self.server.get(self.order_manager._URL).get_json()
        for k in r.keys():
            self.server.delete(self.order_manager._URL, json=k)

        #initialize the server and push the test_data first
        #use dumps because it is more consistent with the ordermanager adding method
        self.server.post(self.order_manager._URL,
                         json={self.test_data_key: json.dumps(self.test_data)})
        self.server.post(
            self.order_manager._URL,
            json={self.test_data_key2: json.dumps(self.test_data2)})

    def test_get_all_order(self):
        #data is a dict where key is string and value is json.dumps dict
        actual = self.order_manager.get_all_orders()
        expected = {
            self.test_data_key: json.dumps(self.test_data),
            self.test_data_key2: json.dumps(self.test_data2)
        }
        assert actual == expected

    def test_get_order_num_exist(self):
        actual = json.loads(self.order_manager.get_order(1))
        expected = self.test_data
        assert actual == expected

    def test_get_order_num_not_exist(self):
        actual = self.order_manager.get_order(4)
        expected = 404
        assert actual == expected

    def test_add_new_order_num_exist(self):
        actual = self.order_manager.add_new_order(self.test_data_key,
                                                  self.test_data)
        expected = 404
        assert actual == expected

    def test_add_new_order_num_not_exist(self):
        actual = self.order_manager.add_new_order(self.test_data_key3,
                                                  self.test_data3)
        expected = 201
        #after adding need to delete, otherwise test_get_all will record one more
        self.server.delete(self.order_manager._URL, json=2)
        assert actual == expected

    def test_delete_order_num_exist(self):
        actual = self.order_manager.delete_order(self.test_data_key)
        expected = 201
        assert actual == expected

    def test_delete_order_num_not_exist(self):
        actual = self.order_manager.delete_order(4)
        expected = 404
        assert actual == expected

    def test_update_order_num_exist(self):
        updated_data2 = {"Toppings": "Pork", "Sizes": "Small"}
        actual = self.order_manager.update_order(self.test_data_key2,
                                                 updated_data2)
        expected = 201
        assert actual == expected

    def test_update_order_num_not_exist(self):
        actual = self.order_manager.update_order(4, None)
        expected = 404
        assert actual == expected

    def test_get_seed(self):
        actual = self.order_manager.get_seed_for_lotto()
        expected = 10
        assert actual == expected

    def test_set_seed(self):
        self.order_manager.set_seed_for_lotto(100)
        actual = self.order_manager.get_seed_for_lotto()
        expected = 100
        assert actual == expected

        # back to original
        self.order_manager.set_seed_for_lotto(10)
        actual = self.order_manager.get_seed_for_lotto()
        expected = 10
        assert actual == expected
Esempio n. 25
0
class GourmetBurgerSystem:
    def __init__(self):
        self._stock_levels = {}
        self._sides = item.initialise_sides(self._stock_levels)
        self._drinks = item.initialise_drinks(self._stock_levels)
        self._ingredients = item.initialise_ingredients(self._stock_levels)
        self._buns = item.initialise_buns(self._stock_levels)
        self._order_manager = OrderManager()
        self._lookup = {}
        obj_list = (*self._sides, *self._drinks, *self._ingredients,
                    *self._buns)
        for obj in obj_list:
            self._lookup[obj.name] = obj

        standard_burger_buns = [self.get_object_by_name("Sesame bun")] * 2
        standard_burger_fillings = [
            self.get_object_by_name(name)
            for name in ("Beef Patty", "Cheddar Cheese", "Tomato Sauce")
        ]
        standard_wrap_fillings = [
            self.get_object_by_name(name)
            for name in ("Chicken Patty", "Tomato", "Lettuce")
        ]

        self._standard_burger = Burger(standard_burger_fillings,
                                       standard_burger_buns)
        self._standard_wrap = Wrap(standard_wrap_fillings)

    @property
    def sides(self):
        return list(self._sides)

    def get_object_by_name(self, name):
        return self._lookup[name]

    @property
    def drinks(self):
        return list(self._drinks)

    @property
    def ingredients(self):
        return list(self._ingredients)

    @property
    def buns(self):
        return list(self._buns)

    @property
    def stock_levels(self):
        return dict(self._stock_levels)

    @property
    def orders(self):
        return self._order_manager.orders

    @property
    def standard_burger(self):
        return self._standard_burger

    @property
    def standard_wrap(self):
        return self._standard_wrap

    def update_stock_levels(self, stock_levels):

        processed_stock_levels = {}
        errors = {}
        messages = {}

        for (key, value) in stock_levels.items():
            if key not in self._stock_levels:
                continue
            try:
                new_value = int(value)
            except ValueError:
                errors[key] = 'Please enter an integer.'
            else:
                if new_value < 0:
                    errors[key] = 'Please enter a stock level greater than 0.'
                elif new_value != self._stock_levels[key][0]:
                    processed_stock_levels[key] = [
                        new_value, self._stock_levels[key][1]
                    ]
                    messages[key] = 'Stock level updated succesfully'

        if errors:
            self._stock_levels.update(processed_stock_levels)
            raise StockSetterError(errors, messages)
        else:
            self._stock_levels.update(processed_stock_levels)
            return messages

    def create_new_order(self):
        return self._order_manager.create_new_order()

    def id_exists(self, id):
        return self._order_manager.id_exists(id)

    def get_order_by_id(self, id):
        return self._order_manager.get_order_by_id(id)

    def print_order(self, id):
        print(self._order_manager.get_order_by_id(id))

    @classmethod
    def load(cls):
        try:
            with open("database", "rb") as file:
                system = pickle.load(file)
        except FileNotFoundError:
            system = GourmetBurgerSystem()
        return system

    def save(self):
        with open("database", "wb") as file:
            pickle.dump(self, file)

    @classmethod
    def checkout(cls, order):

        errors = []

        items = order.list_all()

        cls._increment_all(-1, items)

        items_no_duplicates = list(dict.fromkeys(items))

        errors += cls._list_of_names_with_less_than_zero(items_no_duplicates)

        if errors:
            cls._increment_all(1, items)

            raise OutOfStockError(errors)
        else:
            order.status = "being prepared"

    @classmethod
    def check_item_list(cls, items):
        cls._increment_all(-1, items)

        errors = cls._list_of_names_with_less_than_zero(items)

        cls._increment_all(1, items)

        errors = list(dict.fromkeys(errors))

        if errors:
            raise OutOfStockError(errors)

    @classmethod
    def _list_of_names_with_less_than_zero(cls, items):
        shortages = []
        for item in items:
            if item.stock < 0:
                shortages.append(item.name)
        return shortages

    @classmethod
    def _increment_all(cls, sign, items):
        for item in items:
            item.increment(sign * item.quantity_per_serving)

    def create_burger(self, ingredients, buns):
        return Burger(ingredients, buns)

    def create_wrap(self, ingredients):
        return Wrap(ingredients)

    def add_standard_burger_items(self, item_list):
        for item in self.standard_burger.ingredients:
            item_list.append(item)
        item_list += [self.standard_burger.bun
                      ] * self.standard_burger.number_of_buns

    def add_standard_wrap_items(self, item_list):
        for item in self.standard_wrap.ingredients:
            item_list.append(item)
Esempio n. 26
0
class TestTradingSimulation(unittest.TestCase):
    def setUp(self):
        self.lp_2_gateway = deque()
        self.ob_2_ts = deque()
        self.ts_2_om = deque()
        self.ms_2_om = deque()
        self.om_2_ts = deque()
        self.gw_2_om = deque()
        self.om_2_gw = deque()

        self.liquidityProvider = LiquidityProvider(self.lp_2_gateway)
        self.bookBuilder = OrderBook(self.lp_2_gateway, self.ob_2_ts)
        self.tradingStrategy = TradingStrategy(self.ob_2_ts, self.ts_2_om,
                                               self.om_2_ts)
        self.marketSimulator = MarketSimulator(self.om_2_gw, self.gw_2_om)
        self.orderManager = OrderManager(self.ts_2_om, self.om_2_ts,
                                         self.om_2_gw, self.gw_2_om)

    def test_add_liquidity(self):
        # Order sent from the exchange to the trading system
        order1 = {
            'id': 1,
            'price': 219,
            'quantity': 10,
            'side': 'bid',
            'action': 'new'
        }

        # Add Order from Gateway
        self.liquidityProvider.insert_manual_order(order1)
        self.assertEqual(len(self.lp_2_gateway), 1)

        # Book Builder
        self.bookBuilder.handle_order_from_gateway()
        self.assertEqual(len(self.ob_2_ts), 1)

        # Trading Strategy
        self.tradingStrategy.handle_input_from_bb()
        self.assertEqual(len(self.ts_2_om), 0)

        # Second Order
        order2 = {
            'id': 2,
            'price': 218,
            'quantity': 10,
            'side': 'ask',
            'action': 'new'
        }
        self.liquidityProvider.insert_manual_order(order2.copy())
        self.assertEqual(len(self.lp_2_gateway), 1)

        self.bookBuilder.handle_order_from_gateway()
        self.assertEqual(len(self.ob_2_ts), 1)

        self.tradingStrategy.handle_input_from_bb()
        self.assertEqual(len(self.ts_2_om), 2)

        self.orderManager.handle_input_from_ts()
        self.assertEqual(len(self.ts_2_om), 1)
        self.assertEqual(len(self.om_2_gw), 1)

        self.orderManager.handle_input_from_ts()
        self.assertEqual(len(self.ts_2_om), 0)
        self.assertEqual(len(self.om_2_gw), 2)

        self.marketSimulator.handle_order_from_gw()
        self.assertEqual(len(self.gw_2_om), 1)

        self.marketSimulator.handle_order_from_gw()
        self.assertEqual(len(self.gw_2_om), 2)

        self.orderManager.handle_input_from_market()
        self.orderManager.handle_input_from_market()
        self.assertEqual(len(self.om_2_ts), 2)

        self.tradingStrategy.handle_response_from_om()
        self.assertEqual(self.tradingStrategy.get_pnl(), 0)

        self.marketSimulator.fill_all_orders()
        self.assertEqual(len(self.gw_2_om), 2)

        self.orderManager.handle_input_from_market()
        self.orderManager.handle_input_from_market()
        self.assertEqual(len(self.om_2_ts), 3)

        self.tradingStrategy.handle_response_from_om()
        self.assertEqual(len(self.om_2_ts), 2)

        self.tradingStrategy.handle_response_from_om()
        self.assertEqual(len(self.om_2_ts), 1)

        self.tradingStrategy.handle_response_from_om()
        self.assertEqual(len(self.om_2_ts), 0)
        self.assertEqual(self.tradingStrategy.get_pnl(), 10)