def main_menu(session, base_url):
    """
    Provides the different options for the sample application: Market Quotes, Account List

    :param session: authenticated session
    """

    menu_items = {"1": "Market Quotes",
                  "2": "Account List",
                  "3": "Exit"}

    while True:
        print("")
        options = menu_items.keys()
        for entry in options:
            print(entry + ")\t" + menu_items[entry])
        selection = input("Please select an option: ")
        if selection == "1":
            market = Market(session, base_url)
            market.quotes()
        elif selection == "2":
            accounts = Accounts(session, base_url)
            accounts.account_list()
        elif selection == "3":
            break
        else:
            print("Unknown Option Selected!")
        def createbuyorder():
            readasklist = open("asklist.pickle", "rb")
            asklist = pickle.load(readasklist)
            readasklist.close()

            total = 0
            count = 0

            for ask in asklist:
                total = ask + total
                count = count + 1

            movingaverageFunc = lambda a, b: a / b
            movingaverage = movingaverageFunc(total, count)

            print("Today's Moving Average: ")
            print(movingaverage)
            market = Market(self.session, self.base_url, self.account)
            ask = market.quotes()
            if ask < movingaverage:

                def buy():
                    clientorderId = Generator.get_random_alphanumeric_string(
                        20)

                    # Add payload for POST Request
                    payload = """<PreviewOrderRequest>
                                                      <orderType>EQ</orderType>
                                                      <clientOrderId>{0}</clientOrderId>
                                                      <Order>
                                                          <allOrNone>false</allOrNone>
                                                          <priceType>LIMIT</priceType>
                                                          <orderTerm>GOOD_FOR_DAY</orderTerm>
                                                          <marketSession>REGULAR</marketSession>
                                                          <stopPrice></stopPrice>
                                                          <limitPrice>{1}</limitPrice>
                                                          <Instrument>
                                                              <Product>
                                                                  <securityType>EQ</securityType>
                                                                  <symbol></symbol>
                                                              </Product>
                                                              <orderAction>{2}</orderAction>
                                                              <quantityType>QUANTITY</quantityType>
                                                              <quantity>1</quantity>
                                                          </Instrument>
                                                      </Order>
                                                  </PreviewOrderRequest>"""
                    orderaction = "BUY"
                    payload = payload.format(clientorderId, ask, orderaction)
                    market.preview_order(payload, clientorderId, ask,
                                         orderaction)

                loop.call_soon(buy)
            loop.call_later(300, createbuyorder)
        def calculatetodaysmovingaverage():
            readasklist = open("asklist.pickle", "rb")
            asklist = pickle.load(readasklist)
            readasklist.close()

            market = Market(self.session, self.base_url, self.account)
            ask = market.quotes()

            asklist.append(ask)
            openasklist = open("asklist.pickle", "wb")
            pickle.dump(asklist, openasklist)
            openasklist.close()

            print("Ask Price: ")
            print(ask)

            loop.call_later(300, calculatetodaysmovingaverage)
Example #4
0
    def __init__(self, ticker, year, month, day, latency):
        self.ticker = ticker
        self.year = year
        self.month = month
        self.day = day
        self.latency = latency
        self.my_queue = deque()
        self.mkt_idx = 0
        self.mkt = Market(ticker=ticker)
        date = f'{year}-{month}-{day}'
        self.mkt.date = ticker, date
        self.OrdTuple = namedtuple('Order',
                                   'ordtype uid is_buy qty price timestamp')
        self.my_last_uid = 0 
        # book positions (bid+ask) available in historical data
        BOOK_POS = 20
        
        # load historical orders from csv file
        session = f'./data/orders-{ticker}-{date}.csv'
        csv = pd.read_csv(session, sep=';', float_precision='round_trip')
        csv['timestamp'] = pd.to_datetime(csv['timestamp'])

        # We will be working with ndarrays instead of DataFrames for speed
        self.hist_orders = csv.values
        self.mkt_nord = csv.shape[0]
        
        # we store index positions of columns for array indexing
        columns = csv.columns
        self.col_idx = {}
        for col_name in csv.columns:
            self.col_idx.update({col_name:np.argmax(columns==col_name)})

        # send first 20 orders that will compose first market snapshot
        # this is the real orderbook that was present when the market opened
        # right after the opening auction
        for ord_idx in range(BOOK_POS):   
            self._send_to_market(self.hist_orders[ord_idx], is_mine=False)
        self.mkt_idx = BOOK_POS - 1
        self.mkt_time = self.hist_orders[BOOK_POS-1][self.col_idx['timestamp']]
Example #5
0
class Gateway():
    """ Creates an empty Python Matching Engine (market simulator) and injects 
    real historical orders to it creating the real orderbooks and trades
    that happened in that market session. It also allows you to send
    your own orders to make them interact (i.e. cross) with the historical
    orderbooks that were present that day. The orders you send to the market 
    through this Gateway will also experience latency as they 
    would in real life.
    
    The Gateway allows us to run a synchronous simulation of the interaction
    of your algorithm with a Python Matching Engine (market simulator)
    that will be injected with real life historical orders of a 
    past market session while taking into account the effect
    of this latency. 
    
    For example, when your algorithm receives a new market best bid price,
    actually this price happened "md_latency" microseconds in the past, 
    the time it took to reach your algorithm. Your algo will take "algo_latency"
    microseconds to make a decission and send a message (new/cancel/modif),
    and finally, this message will take "mkt_latency" microseconds to reach
    the market because of the physical distance and the different systems
    it needs to cross through before reaching the market. 
    
    The total latency will be: 
        latency = md_latency + algo_latency + mkt_latency
    
    When you send messages to a market through this Gateway, 
    your messages will reach the market "latency" microseconds 
    after the time of the last historical order that reached the market
    and that produced the last market data update upon which your
    algo made its last decission.     
        
    Args:
        ticker (str): symbol of the shares
        year (int): year
        month (int): month
        day (int): day
        latency (int): mean latency in microseconds that we expect 
                        our orders to have in real life when sent 
                        to the market (market data one way 
                                     + algo decission time
                                     + market access one way)        
                
    """
    
    def __init__(self, ticker, year, month, day, latency):
        self.ticker = ticker
        self.year = year
        self.month = month
        self.day = day
        self.latency = latency
        self.my_queue = deque()
        self.mkt_idx = 0
        self.mkt = Market(ticker=ticker)
        date = f'{year}-{month}-{day}'
        self.mkt.date = ticker, date
        self.OrdTuple = namedtuple('Order',
                                   'ordtype uid is_buy qty price timestamp')
        self.my_last_uid = 0 
        # book positions (bid+ask) available in historical data
        BOOK_POS = 20
        
        # load historical orders from csv file
        session = f'./data/orders-{ticker}-{date}.csv'
        csv = pd.read_csv(session, sep=';', float_precision='round_trip')
        csv['timestamp'] = pd.to_datetime(csv['timestamp'])

        # We will be working with ndarrays instead of DataFrames for speed
        self.hist_orders = csv.values
        self.mkt_nord = csv.shape[0]
        
        # we store index positions of columns for array indexing
        columns = csv.columns
        self.col_idx = {}
        for col_name in csv.columns:
            self.col_idx.update({col_name:np.argmax(columns==col_name)})

        # send first 20 orders that will compose first market snapshot
        # this is the real orderbook that was present when the market opened
        # right after the opening auction
        for ord_idx in range(BOOK_POS):   
            self._send_to_market(self.hist_orders[ord_idx], is_mine=False)
        self.mkt_idx = BOOK_POS - 1
        self.mkt_time = self.hist_orders[BOOK_POS-1][self.col_idx['timestamp']]

    

    def _send_to_market(self, order, is_mine):
        """ Send an order/modif/cancel to the market
        
            Args:
                order (ndarray): order to be sent
                is_mine (bool): False if historical, True if user sent
        """
        
        
        ord_type = order[self.col_idx['ordtype']]
        if ord_type == "new":
            self.mkt.send(is_buy=order[self.col_idx['is_buy']],
                            qty=order[self.col_idx['qty']],
                            price=order[self.col_idx['price']],
                            uid=order[self.col_idx['uid']],
                            is_mine=is_mine,
                            timestamp=order[self.col_idx['timestamp']])
        elif ord_type == "cancel":
            self.mkt.cancel(uid=order[self.col_idx['uid']])
        elif ord_type == "modif":
            self.mkt.modif(uid=order[self.col_idx['uid']],                           
                           new_qty=order[self.col_idx['qty']])
        else:
            raise ValueError(f'Unexpected ordtype: {ord_type}')
            
    
    def move_n_seconds(self, n_seconds):
        """ 
        """
        
        stop_time = self.mkt_time + timedelta(0, n_seconds)
        
        while (self.mkt_time<=stop_time):
            self.tick()
        
        self.mkt_time = stop_time


    def _send_historical_order(self, mktorder):
        self.mkt_idx += 1        
        self._send_to_market(mktorder, is_mine=False)
        self.mkt_time = mktorder[self.col_idx['timestamp']]


    def move_until(self, stop_time):
        """ 
        
        Params:
            stop_time (datetime):         
                
        """
        
        while (self.mkt_time <= stop_time):
            mktorder = self.hist_orders[self.mkt_idx+1]
            self._send_historical_order(mktorder)


    def tick(self):
        """ Move the market forward one tick (process next order)
        
            If the user has messages (new/cancel/modif) queued, it will
            decide whether to send a user or historical order based on
            their theoretical arrival time (timestamp)
        """
        
        # next historical order to be sent
        mktorder = self.hist_orders[self.mkt_idx+1]
        # if I have queued orders
        if self.my_queue:
            # if my order reaches the market before the next historical order
            if self.my_queue[0].timestamp < mktorder[self.col_idx['timestamp']]:
                my_order = self.my_queue.popleft()
                self._send_to_market(my_order, is_mine=True)
                self.mkt_time = my_order[self.col_idx['timestamp']]
                return
        
        # otherwise sent next historical order
        self._send_historical_order(mktorder)

        
    def queue_my_new(self, is_buy, qty, price):
        """ Queue a user new order to be sent to the market when time is due 
        
            Args:
                is_buy (bool): True for buy orders
                qty (int): quantity or volume
                price (float): limit price of the order
                
            Reuturns:
                An int indicating the uid that the market will assign to
                it when it is introudced.
                NOTES: as the order is queued by this function, its uid does
                not exist yet in the market. It will not exist until 
                the time is due and the order reaches the market. Requesting
                the status of this uid will therefore raise a KeyError
                meanwhile.
                Uids of user orders will be negative, this
                way we ensure no collisions with historical positive uids and 
                have an easy way to know if an order is ours                
                
        """        
        
        self.my_last_uid -= 1                
        message = self.OrdTuple(ordtype="new",
                                    uid=self.my_last_uid,
                                    is_buy=is_buy,
                                    qty=qty,
                                    price=price,                              
                                    timestamp=self._arrival_time())        
        self.my_queue.append(message)        
        return self.my_last_uid 

    
    def queue_my_modif(self, uid, new_qty):
        """ Modify an order identified by its uid without loosing priority.
        Modifications can only downsize the volume. 
        If you attempt to increase the volume, the
        modification message will do nothing. Downsizing volume will 
        mantain your price-time priority in the market. If you want to
        increase volume or change price, you need to cancel your previous
        order and send a new one. 
        
        Args:
            uid (int): uid of our order to be modified
            new_qty(int): new quantity. Only downsizing allowed. 
        
        """
                
        message = self.OrdTuple(ordtype="modif",
                                    uid=uid,
                                    is_buy=np.nan,
                                    qty=new_qty,
                                    price=np.nan,                              
                                    timestamp=self._arrival_time())        
        self.my_queue.append(message)        
    
    
    def queue_my_cancel(self, uid):
        """ Cancel an order by its uid
        
        """
                
        message = self.OrdTuple(ordtype="cancel",
                                    uid=uid,
                                    is_buy=np.nan,
                                    qty=np.nan,
                                    price=np.nan,                              
                                    timestamp=self._arrival_time())        
        self.my_queue.append(message)        
    
    
    def ord_status(self, uid):
        """ Returns the current mkt status of an order identified by its uid.
        
        Args:
            uid (int): unique order identifier
        
        NOTE: when an order is queued, its uid does not exist yet in the
        market since it did not arrive there yet. Calling this function
        on a uid that is queued by not yet in the market will raise a 
        KeyError exception that will have to be handled.        
        
        """
        # TODO: use ticker to select market orderbook
        return self.mkt.get(uid)

    
    def _arrival_time(self):
        """ Returns the estimated time of arrival of an order
        
        """
        
        return self.mkt_time + timedelta(0, 0, self.latency)


    def plot(self):
        trades = pd.DataFrame(self.mkt.trades)
        
        
        
Example #6
0
class Trader():
    """
    Trader operates with client's actives over market
    """
    def __init__(self):
        self.__store = Store()
        self.__market = Market()

    def get_clients_for(self, broker):
        """
        :param broker: id of broker where clients are searched for
        :return: list of clients in format:{
            'name': 'CoolClient',
            'balance': 1056.33
        }
        """

        return self.__store.clients(broker)

    def get_brokers(self):
        """
        :return: list of brokers (full info, e.g. id, name, rating)
        """

        return self.__store.brokers(True)

    def get_brokers_id(self):
        """
        :return: list of brokers (id only)
        """

        return self.__store.brokers()

    def get_actives_for(self, client):
        """
        returns list of actives for given client, by actives means shares like (oil, gold, currency etc)
        :param client: client's ID
        :return: list of actives in format:{
            'name': 8899,
            'quantity': 125365
        },
        """

        return self.__store.actives(client)

    def update_active_for(self, code, quantity):
        """
        update number of shares for given code
        :param code: code of shares that will be updated
        :param code: new number of shares
        """

        self.__store.update_active(code, quantity)

    def update_balance_for(self, client, new_balance):
        """
        updates balance for given client
        :param client: ID of the client
        :param new_balance: new amount of money
        """

        self.__store.update_balance(client, new_balance)

    def trade(self):
        """
        starts trade procedure for all brokers
        :return:
        """
        logging.info('------------- Start trading -------------')
        for broker in self.get_brokers_id():
            logging.info('---> Broker\'s ID: {0}'.format(broker))
            self.trade_client_for(broker)
        logging.info('------------- end trading -------------')

    def trade_client_for(self, broker):
        """
        requests all clients that belongs to the broker and starts trading
        :param broker: broker's ID
        :return:
        """

        for client in self.get_clients_for(broker):
            logging.info('------> Client: {0}'.format(client))
            self.trade_shares_for(client)

    def trade_shares_for(self, client):
        """
        requests all shares for client, than requests shares prices from market
        and based on market's recommendation trades
        :param client: dict {'idclients':1, 'name':'CL', 'balance':256.33}
        :return:
        """

        # TODO: optimization! Firstly, should be sold all shares to get additional money, then perform buy action

        actives = self.get_actives_for(client['idclients'])
        for active in actives:
            try:  # in case of bad answer from the market will be returned empty dict - will ignore it
                logging.info('Request data for {0}'.format(active))
                share_code = active['code']

                market_share = self.__market.get_share(
                    share_code)  # share_code is string!!!

                # will construct 'deal' abstraction,
                # could be buy/sell/neutral or active buy/sell
                # the abstraction will perform transaction
                info_for_share = market_share[share_code]
                # price = Shares().get_price_in_usd(int(share_code), info_for_share['price'])  # convert to USD
                deal = construct_deal_for(info_for_share['summary'])
                deal(client, active, info_for_share['price'])
                logging.info('Market info for {0}'.format(market_share))
            except KeyError:
                logging.error('Wrong answer for {0}'.format(active['code']))

        # TODO: updated client's balance and shares quantity should be stored as one transaction
        self.update_balance_for(client['idclients'], client['balance'])
        for active in actives:
            self.update_active_for(active['idactives'], active['quantity'])
Example #7
0
 def __init__(self):
     self.__store = Store()
     self.__market = Market()
Example #8
0
                add_ohlcv_records(klines_list)
                # 防止速度过快
                if i % 10 == 0:
                    time.sleep(1)
            except Exception as e:
                print('error', 'add_ohlcv')
                traceback.print_exc()
                time.sleep(10)


if __name__ == '__main__':
    # 交易所
    ex_names = ['binance']
    for ex_name in ex_names:
        try:
            m1 = Market(ex_name)
            print(m1.ex_name)
            # ms = self.exchange.fetch_markets()
            ms = m1.exchange.load_markets(reload=True)
            ms_count = len(ms)
            print('markets', ms_count)
            symbols = []
            for s in ms:
                base_currency = s.split('/')[0]
                quote_currency = s.split('/')[1]
                if quote_currency not in ['USDT', 'BTC', 'ETH']:
                    continue
                # print(s)
                symbols.append(s)
            add_ohlcv(m1, symbols, '1m')
        except Exception as e:
Example #9
0
    # print(info)

    # Discover available carparts
    print('Discovering all carparts and materials... ', end='')
    partcount, materialcount = discover_parts()
    print('Found %d carparts and %d materials' % (partcount, materialcount))

    # Discover available apps
    print('Discovering all apps... ', end='')
    appcount = discover_apps()
    print('Found %d apps' % appcount)

    # init Game Objects
    env = Environment()
    gv.company = Company()
    gv.market = Market()
    gv.computer = Computer()
    w = world.world.World()
    w.add(
        world.buildings.shed.Shed(
            (screensize[0] * 0.5 - 40, screensize[1] * 0.52)))
    w.add(
        world.buildings.small_office.SmallOffice(
            (screensize[0] * 0.7 - 40, screensize[1] * 0.52)))
    w.add_road((8, 9))
    w.add_road((9, 9))
    w.add_road((10, 9))
    w.add_road((11, 9))
    w.add_road((12, 9))
    w.add_road((13, 9))
    w.add_road((14, 9))
Example #10
0
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 17 17:26:49 2019

@author: fmerlos
"""

from market.market import Market

# initialize an empty market book for Santander shares (san)
mkt = Market(ticker='san')

# Not all prices are allowed. Check MiFID II tick-size regime
# Move n ticks from one price
mkt.get_new_price(price=10, n_moves=1)
mkt.get_new_price(price=10, n_moves=-1)

# fill with different passive orders
mkt.send(uid=-1, is_buy=True, qty=100, price=10.)
mkt.send(uid=-2, is_buy=True, qty=80, price=10.)
mkt.send(uid=-3, is_buy=True, qty=90, price=10.)
mkt.send(uid=-4, is_buy=True, qty=70, price=mkt.get_new_price(10., -1))
mkt.send(uid=-5, is_buy=False, qty=60, price=mkt.get_new_price(10., 2))
mkt.send(uid=-6, is_buy=False, qty=30, price=mkt.get_new_price(10., 1))
mkt.send(uid=-7, is_buy=False, qty=50, price=mkt.get_new_price(10., 1))

# Show current market orderbook
print(mkt)

# Show book dictionary of LevelPrices 
mkt._bids.book
Example #11
0
"""This Python script provides examples on using the E*TRADE API endpoints"""
from __future__ import print_function
import json
import sys
import requests
from rauth import OAuth1Session
from market.market import Market

with open('.etrade-oauth.json', 'r') as f:
    info_deserialized = json.load(f)

session = OAuth1Session(**info_deserialized)
base_url = 'https://api.etrade.com'
market = Market(session, base_url)

for param in sys.argv[1:]:

    quotes = market.quotes(param)

    for stock in quotes:
        symbol = stock['Product']['symbol']

        chainDates = market.chainDates(symbol)

        chains = [{
            'Expiration':
            chainDate,
            **market.chains(
                symbol, {
                    'expiryYear': chainDate['year'],
                    'expiryMonth': chainDate['month'],