class TagoRealTime:
    def __init__(self, address, token, callback):
        self.socket = SocketIO(address, 443, LoggingNamespace)
        self.token = token
        self.callback = callback

    def on_connect(self):
        self.socket.emit('register', self.token)

    def listening(self, channel, wait):
        self.socket.on('connect', self.on_connect)
        self.socket.on(channel, self.callback)

        if wait:
            self.socket.wait(seconds=wait)
        else:
            self.socket.wait()

        return self.socket

    def stopListening(self, channel):
        self.socket.off(channel)
Exemple #2
0
class Trader(object):
    '''FXCM REST API abstractor.
    Obtain a new instance of this class and use that
    to do all trade and account actions.
    '''
    def __init__(self,
                 access_token,
                 environment,
                 messageHandler=None,
                 purpose='General',
                 config_file="fxcm_rest.json"):
        self.config_file = config_file
        self.initialize()
        self.socketIO = None
        self.updates = {}
        self.symbols = {}
        self.symbol_info = {}
        self.symbol_id = {}
        self.account_id = None
        self.account_list = []
        self.accounts = {}
        self.orders_list = {}
        self.trades = {}
        self.subscriptions = {}
        self.open_list = []
        self.closed_list = []
        self.currency_exposure = {}
        self.access_token = access_token
        self.env = environment
        self.purpose = purpose

        # for debugging - allows the suppression of specific messages
        # sent to self.Print.Helpful for when logging to console and
        # you want to keep log level, but remove some messages from the output
        self.ignore_output = []
        #####

        self.update_handlers = {
            "Offer": self.on_offer,
            "Account": self.on_account,
            "Order": self.on_order,
            "OpenPosition": self.on_openposition,
            "ClosedPosition": self.on_closedposition,
            "Summary": self.on_summary,
            "LeverageProfile": self.on_leverageprofile,
            "Properties": self.on_properties
        }

        if messageHandler is not None:
            self.message_handler = self.add_method(messageHandler)
        else:
            self.message_handler = self.on_message
        self.list = self.CONFIG.get('subscription_list', [])
        self.environment = self._get_config(environment)
        # self.login()

    def login(self):
        '''
        Once you have an instance, run this method to log in to the service.
        Do this before any other calls
        :return: Dict
        '''
        #self.socketIO = SocketIO(self.environment.get("trading"),
        #                         self.environment.get("port"),
        #                         params={'access_token':
        #                                 self.access_token})
        self._log_init()
        self.socketIO = SocketIO(self.environment.get("trading"),
                                 self.environment.get("port"),
                                 params={'access_token': self.access_token})
        self.socketIO.on('connect', self.on_connect)
        self.socketIO.on('disconnect', self.on_disconnect)
        thread_name = self.access_token + self.env + self.purpose
        for thread in threading.enumerate():
            if thread.name == thread_name:
                thread.keepGoing = False
        self._socketIO_thread = threading.Thread(target=self.socketIO.wait)
        self._socketIO_thread.setName(thread_name)
        self._socketIO_thread.keepGoing = True
        self._socketIO_thread.setDaemon(True)
        self._socketIO_thread.start()
        return self.__return(True, "Connecting")

    def bearerGen(self):
        return ("Bearer " + self.socketIO._engineIO_session.id +
                self.access_token)

    def on_connect(self):
        '''
        Actions to be preformed on login. By default will subscribe to updates
        for items defined in subscription_list. subscription_list is in the
        json self.CONFIG with options explained there. If messageHandler was
        passed on instantiation, that will be used to handle all messages.
        Alternatively, this method can be overridden before login is called to
        provide different on_connect functionality.

        :return: None
        '''
        self.logger.info('Websocket connected: ' +
                         self.socketIO._engineIO_session.id)
        self.bearer = self.bearerGen()
        self.HEADERS['Authorization'] = self.bearer
        accounts = self.get_model("Account").get('accounts', {})
        self.account_list = [a['accountId'] for a in accounts]
        self.account_id = None
        for account in accounts:
            account_id = account['accountId']
            self.accounts[account_id] = account
            if self.account_id is None and account_id != '':
                self.account_id = account_id

        self.get_offers()
        for item in self.list:
            handler = self.update_handlers.get(item, None)
            if handler is None:
                self.subscribe(item)
            else:
                self.subscribe(item, handler)

    def Print(self, message, message_type=None, level='INFO'):
        loggers = dict(INFO=self.logger.info,
                       DEBUG=self.logger.debug,
                       WARNING=self.logger.warning,
                       ERROR=self.logger.error,
                       CRITICAL=self.logger.critical)
        if message_type is None or message_type not in self.ignore_output:
            loggers[level](message)

    def add_method(self, method):
        '''
        Returns a method suitable for addition to the instance.
        Can be used to override methods without subclassing.
        self.on_connect = self.add_method(MyConnectMethodHandler)
        :param method:
        :return: instance method
        '''
        return types.MethodType(method, self)

    def logout(self):
        '''
        Unsubscribes from all subscribed items and logs out.
        :return:
        '''
        for item in self.subscriptions.keys():
            self.subscriptions.pop(item)
            self.socketIO.off(item)
        self.send("/logout")

    def _loop(self):
        while self._socketIO_thread.keepGoing:
            self.socketIO.wait(1)

    def __exit__(self, *err):
        pass

    def __enter__(self):
        return self

    def __return(self, status, data):
        ret_value = {'status': status}
        if type(data) == dict:
            ret_value.update(data)
        else:
            ret_value.update({'data': data})
        return ret_value

    def _send_request(self, method, command, params, additional_headers={}):
        self.HEADERS['Authorization'] = self.bearerGen()
        self.logger.info(
            self.environment.get("trading") + command + str(params))
        if method == 'get':
            rresp = requests.get(self.environment.get("trading") + command,
                                 params=params,
                                 headers=self.HEADERS)
        else:
            # params = json.dumps(params)
            rresp = requests.post(self.environment.get("trading") + command,
                                  headers=self.HEADERS,
                                  data=params)
        if rresp.status_code == 200:
            data = rresp.json()
            if data["response"]["executed"] is True:
                return self.__return(True, data)
            return self.__return(False, data["response"]["error"])
        else:
            return self.__return(False, rresp.status_code)

    def send(self, location, params={}, method='post', additional_headers={}):
        '''
        Method to send REST requests to the API

        :param location: eg. /subscribe
        :param params:  eg. {"pairs": "USD/JPY"}
        :param method: GET, POST, DELETE, PATCH
        :return: response Dict
        '''
        try:
            response = self._send_request(method, location, params,
                                          additional_headers)
            return response
        except Exception as e:
            self.logger.error("Failed to send request [%s]: %s" % (params, e))
            status = False
            response = str(e)
            return self.__return(status, response)

    def _get_config(self, environment):
        ret = self.CONFIG.get("environments", {}).get(environment, {})
        if ret == {}:
            self.logger.error(
                "No self.CONFIGuration found. Please call your trade object with\
                 'get_self.CONFIG(environment)'.")
            self.logger.error("Environments are demo or real.")
        return ret

    def _log_init(self):
        self.logger = logging.getLogger(self.access_token + "_" + self.env +
                                        "_" + str(uuid.uuid4())[:8])
        self.ch = logging.StreamHandler()
        self.set_log_level(self.debug_level)
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        self.ch.setFormatter(formatter)
        self.logger.addHandler(self.ch)

    def _forget(self, subscribed_item):
        if subscribed_item in self.subscriptions:
            try:
                self.subscriptions.pop(subscribed_item)
            except Exception:
                pass

    def set_log_level(self, level):
        '''
        set the logging level of the specific instance.
        Levels are DEBUG, INFO, WARNING, ERROR, CRITICAL
        :param level: Defaults to ERROR if log level is undefined

        :return: None
        '''
        self.logger.setLevel(self.LOGLEVELS.get(level, "ERROR"))
        self.ch.setLevel(self.LOGLEVELS.get(level, "ERROR"))

    def _add_method(self):
        pass

# Obtain and store the list of instruments in the symbol_info dict

    def get_offers(self):
        response = self.get_model("Offer")
        if response['status'] is True:
            for item in response['offers']:
                self.symbol_info[item['currency']] = item
                self.symbol_id[item['offerId']] = item['currency']

    def on_disconnect(self):
        '''
        Simply logs info of the socket being closed.
        Override to add functionality

        :return: None
        '''
        self.logger.info("Websocket closed")

    def register_handler(self, message, handler):
        '''
        Register a callback handler for a specified message type

        :param message: string
        :param handler: function
        :return: None
        '''
        self.socketIO.on(message, handler)

    def on_price_update(self, msg):
        '''
        Sample price handler. If on_price_update is registered for a symbol,
        it will update the symbol's values (stored in a symbol hash) with
        that price update.symbol hash.

        :return: none
        '''
        try:
            md = json.loads(msg)
            symbol = md["Symbol"]
            symbol_info = self.symbol_info.get(symbol, {})
            p_up = dict(symbol_info=self.symbol_info[symbol], parent=self)
            self.symbols[symbol] = self.symbols.get(
                symbol, PriceUpdate(p_up, symbol_info=symbol_info))
            self.symbols[symbol].bid, self.symbols[symbol].ask,\
                self.symbols[symbol].high,\
                self.symbols[symbol].low = md['Rates']
            self.symbols[symbol].updated = md['Updated']
        except Exception as e:
            self.logger.error("Can't handle price update: " + str(e))

    def on_offer(self, msg):
        message = json.loads(msg)
        self.Print("Offer Update:" + message, "Offer", "INFO")

    def on_account(self, msg):
        message = json.loads(msg)
        account_id = message['accountId']
        self.accounts[account_id] = self.accounts.get(account_id, {})
        self.accounts[account_id].update(message)
        # self.Print("Account Update:" + msg, "Account", "INFO")

    def on_order(self, msg):
        message = json.loads(msg)
        order_id = message.get('orderId', '')
        trade_id = message.get('tradeId', '')
        self.orders_list[order_id] = self.orders_list.get(
            order_id, {'actions': []})
        if "action" in message:
            self.orders_list[order_id]['actions'].append(message)
        self.orders_list[order_id].update(message)
        self.Print("Order Update:" + msg, "Order", "INFO")

    def on_openposition(self, msg):
        message = json.loads(msg)
        self.Print("OpenPosition Update:" + msg, "OpenPosition", "INFO")

    def on_closedposition(self, msg):
        message = json.loads(msg)
        self.Print("ClosedPosition Update:" + msg, "ClosedPosition", "INFO")

    def on_summary(self, msg):
        message = json.loads(msg)
        self.Print("Summary Update:" + msg, "Summary", "INFO")

    def on_properties(self, msg):
        message = json.loads(msg)
        if "offerId" in message:
            message['symbol'] = self.symbol_id[message['offerId']]
        self.Print("Property Update:" + msg, "Property", "INFO")

    def on_leverageprofile(self, msg):
        message = json.loads(msg)
        self.Print("LeverageProfile Update:" + msg, "LeverageProfile", "INFO")

    def on_message(self, msg):
        '''
        Sample generic message handling.
        Will update that specific message type with the latest message

        :return:
        '''
        self.Print(msg, -1, "INFO")

    @property
    def summary(self):
        '''
        Provides a summary snapshot ofthe account
        '''
        return self.get_model("Summary").get('summary', [])

    @property
    def offers(self):
        return self.get_model("Offer").get('offers', [])

    @property
    def open_positions(self):
        return self.get_model('OpenPosition').get('open_positions', [])

    @property
    def closed_positions(self):
        return self.get_model('ClosedPosition').get('closed_positions', [])

    @property
    def orders(self):
        return self.get_model('Order').get('orders', [])

    @property
    def leverage_profile(self):
        return self.get_model("LeverageProfile").get('leverage_profile', [])

    @property
    def properties(self):
        return self.get_model("Properties").get('properties', [])

    def subscribe_symbol(self, instruments, handler=None):
        '''
        Subscribe to given instrument

        :param instruments:
        :return: response Dict
        '''
        handler = handler or self.on_price_update
        if type(instruments) is list:
            for instrument in instruments:
                self.subscriptions[instrument] = instrument
                self.socketIO.on(instrument, handler)
        else:
            self.subscriptions[instruments] = instruments
            self.socketIO.on(instruments, handler)
        return self.send("/subscribe", {"pairs": instruments},
                         additional_headers={'Transfer-Encoding': "chunked"})

    def unsubscribe_symbol(self,
                           instruments,
                           headers={'Transfer-Encoding': "chunked"}):
        '''
        Unsubscribe from instrument updates

        :param instruments:
        :return: response Dict
        '''
        if type(instruments) is list:
            for instrument in instruments:
                self._forget(instrument)
                self.socketIO.off(instrument)
        else:
            self.socketIO.off(instruments)
            self._forget(instruments)
        return self.send("/unsubscribe", {"pairs": instruments})

    def subscribe(self, items, handler=None):
        '''
        Subscribes to the updates of the data models.
        Update will be pushed to client via socketIO
        Model choices: 'Offer', 'OpenPosition', 'ClosedPosition',
        'Order',  'Account',  'Summary', 'LeverageProfile', 'Properties'

        :param item:
        :return: response Dict
        '''
        handler = handler or self.on_message
        response = self.send("/trading/subscribe", {"models": items})
        if response['status'] is True:
            if type(items) is list:
                for item in items:
                    self.socketIO.on(item, handler)
            else:
                self.socketIO.on(items, handler)
        else:
            self.logger.error("Error processing /trading/subscribe:" +
                              str(response))
        return response

    def unsubscribe(self, items):
        '''
        Unsubscribe from model
        ["Offer","Account","Order","OpenPosition","Summary","Properties"]

        :param item:
        :return: response Dict
        '''
        if type(items) is list:
            for item in items:
                self._forget(item)
                self.socketIO.off(item)
        else:
            self._forget(items)
            self.socketIO.off(items)
        return self.send("/trading/unsubscribe", {"models": items})

    def get_tradeId(self, orderId):
        try:
            orderId = str(orderId)
            tradeId = None
            order = self.orders_list.get(orderId, {})
            for action in order.get('actions', []):
                tradeId = action.get('tradeId', None)
                if tradeId is not None:
                    break
            return tradeId
        except Exception as e:
            return {'Error': 'Error ' + str(e)}

    def get_model(self, item):
        '''
        Gets current content snapshot of the specified data models.
        Model choices:
        'Offer', 'OpenPosition', 'ClosedPosition', 'Order', 'Summary',
        'LeverageProfile', 'Account', 'Properties'

        :param item:
        :return: response Dict
        '''
        return self.send("/trading/get_model", {"models": item}, "get")

    def change_password(self, oldpwd, newpwd):
        '''
        Change user password

        :param oldpwd:
        :param newpwd:
        :return: response Dict
        '''
        return self.send("/trading/changePassword", {
            "oldPswd": oldpwd,
            "newPswd": newpwd,
            "confirmNewPswd": newpwd
        })

    def permissions(self):
        '''
        Gets the object which defines permissions for the specified account
        identifier and symbol. Each property of that object specifies the
        corresponding permission ("createEntry", "createMarket",
        "netStopLimit", "createOCO" and so on).
        The value of the property specifies the permission status
        ("disabled", "enabled" or "hidden")


        :param item:
        :return: response Dict
        '''
        return self.send("/trading/permissions", {}, "get")

    def open_trade(self,
                   account_id,
                   symbol,
                   is_buy,
                   amount,
                   rate=0,
                   at_market=0,
                   time_in_force="GTC",
                   order_type="AtMarket",
                   stop=None,
                   trailing_step=None,
                   limit=None,
                   is_in_pips=None):
        '''
        Create a Market Order with options for At Best or Market Range,
        and optional attached stops and limits.

        :param account_id:
        :param symbol:
        :param is_buy:
        :param amount:
        :param rate:
        :param at_market:
        :param time_in_force:
        :param order_type:
        :param stop: * Optional *
        :param trailing_step: * Optional *
        :param limit: * Optional *
        :param is_in_pips: * Optional *
        :return: response Dict
        '''
        if None in [account_id, symbol, is_buy, amount]:
            ret = "Failed to provide mandatory parameters"
            return self.__return(False, ret)

        is_buy = 'true' if is_buy else 'false'
        is_in_pips = 'true' if is_in_pips else 'false'
        params = dict(account_id=account_id,
                      symbol=symbol,
                      is_buy=is_buy,
                      amount=amount,
                      rate=rate,
                      at_market=at_market,
                      time_in_force=time_in_force,
                      order_type=order_type)
        if stop is not None:
            params['stop'] = stop

        if trailing_step is not None:
            params['trailing_step'] = trailing_step

        if limit is not None:
            params['limit'] = limit

        if is_in_pips is not None:
            params['is_in_pips'] = is_in_pips
        return self.send("/trading/open_trade", params)

    def close_trade(self,
                    trade_id,
                    amount,
                    at_market=0,
                    time_in_force="GTC",
                    order_type="AtMarket",
                    rate=None):
        '''
        Close existing trade

        :param trade_id:
        :param amount:
        :param at_market:
        :param time_in_force:
        :param order_type:
        :param rate: * Optional *
        :return: response Dict
        '''
        if None in [trade_id, amount, at_market, time_in_force, order_type]:
            ret = "Failed to provide mandatory parameters"
            return self.__return(False, ret)
        params = dict(trade_id=trade_id,
                      amount=amount,
                      at_market=at_market,
                      time_in_force=time_in_force,
                      order_type=order_type)
        if rate is not None:
            params['rate'] = rate
        return self.send("/trading/close_trade", params)

    def change_order(self, order_id, rate, rng, amount, trailing_step=None):
        '''
        Change order rate/amount

        :param order_id:
        :param rate:
        :param range:
        :param amount:
        :param trailing_step: * Optional *
        :return: response Dict
        '''
        if None in [order_id, amount, rate, rng]:
            ret = "Failed to provide mandatory parameters"
            return self.__return(False, ret)
        params = dict(order_id=order_id, rate=rate, range=rng, amount=amount)
        if trailing_step is not None:
            params['trailing_step'] = trailing_step
        return self.send("/trading/change_order", params)

    def delete_order(self, order_id):
        '''
        Delete open order

        :param order_id:
        :return: response Dict
        '''
        if None in [order_id]:
            ret = "Failed to provide mandatory parameters"
            return self.__return(False, ret)
        params = dict(order_id=order_id)
        return self.send("/trading/delete_order", params)

    def create_entry_order(self,
                           account_id,
                           symbol,
                           is_buy,
                           rate,
                           amount,
                           is_in_pips,
                           order_type,
                           time_in_force,
                           limit=None,
                           stop=None,
                           trailing_step=None):
        """
        Create a Limit Entry or a Stop Entry order.
        An order priced away from the market (not marketable)
        will be submitted as a Limit Entry order. An order priced through the
        market will be submitted as a Stop Entry order.

        If the market is at 1.1153 x 1.1159
        *   Buy Entry order @ 1.1165 will be processed as a
            Buy Stop Entry order.
        *   Buy Entry order @ 1.1154 will be processed as a
            Buy Limit Entry order

        :param account_id:
        :param symbol:
        :param is_buy:
        :param amount:
        :param limit:
        :param is_in_pips:
        :param order_type:
        :param time_in_force:
        :param rate:
        :param stop: * Optional *
        :param trailing_step: * Optional *
        :return: response Dict
        """
        if None in [
                account_id, symbol, is_buy, amount, rate, is_in_pips,
                order_type, time_in_force
        ]:
            ret = "Failed to provide mandatory parameters"
            return self.__return(False, ret)
        is_buy = 'true' if is_buy else 'false'
        is_in_pips = 'true' if is_in_pips else 'false'
        params = dict(account_id=account_id,
                      symbol=symbol,
                      is_buy=is_buy,
                      amount=amount,
                      rate=rate,
                      is_in_pips=is_in_pips,
                      time_in_force=time_in_force,
                      order_type=order_type)
        if stop is not None:
            params['stop'] = stop
        if limit is not None:
            params['limit'] = limit
        if trailing_step is not None:
            params['trailing_step'] = trailing_step
        return self.send("/trading/create_entry_order", params)

    def simple_oco(self, account_id, symbol, amount, is_in_pips, time_in_force,
                   expiration, is_buy, rate, stop, trailing_step, is_in_pips2,
                   trailing_stop_step, limit, at_market, order_type, is_buy2,
                   rate2, stop2, trailing_step2, trailing_stop_step2, limit2):
        '''
        Create simple OCO

        :param account_id:
        :param symbol:
        :param amount:
        :param is_in_pips:
        :param time_in_force:
        :param expiration:
        :param is_buy:
        :param rate:
        :param stop:
        :param trailing_step:
        :param trailing_stop_step:
        :param limit:
        :param at_market:
        :param order_type:
        :param is_buy2:
        :param rate2:
        :param stop2:
        :param trailing_step2:
        :param trailing_stop_step2:
        :param limit2:
        :return: response Dict
        '''
        items = locals().items()
        params = {}
        is_buy = 'true' if is_buy else 'false'
        is_in_pips = 'true' if is_in_pips else 'false'
        try:
            for k, v in items:
                if k != "self":
                    params[k] = v
            return self.__return(self.send("/trading/simple_oco", params))
        except Exception as e:
            return (False, str(e))

    def add_to_oco(self, orderIds, ocoBulkId):
        '''
        Add order(s) to an OCO

        :param orderIds:
        :param ocoBulkId:
        :return: response Dict
        '''
        return self.send("/trading/add_to_oco", {
            "orderIds": orderIds,
            "ocoBulkId": ocoBulkId
        })

    def remove_from_oco(self, orderIds):
        '''
        Remove order(s) from OCO

        :param orderIds:
        :return: response Dict
        '''
        return self.send("/trading/remove_from_oco", {"orderIds": orderIds})

    def edit_oco(self, ocoBulkId, addOrderIds, removeIds):
        '''
        Edit an OCO

        :param ocoBulkId:
        :param addOrderIds:
        :param removeOrderIds:
        :return: response Dict
        '''
        return self.send(
            "/trading/edit_oco", {
                "ocoBulkId": ocoBulkId,
                "addOrderIds": addOrderIds,
                "removeOrderIds": removeIds
            })

    def change_trade_stop_limit(self,
                                trade_id,
                                is_stop,
                                rate,
                                is_in_pips=False,
                                trailing_step=0):
        '''
        Creates/removes/changes the stop/limit order for the specified trade.
        If the current stop/limit rate for the specified trade is not set
        (is zero) and the new rate is not zero, then creates a new order.
        If the current stop/limit rate for the specified trade is set
        (is not zero), changes order rate (if the new rate is not zero) or
        deletes order (if the new rate is zero).


        :param trade_id:
        :param is_stop:
        :param rate:
        :param is_in_pips:
        :param trailing_step:
        :return: response Dict
        '''
        is_stop = 'true' if is_stop else 'false'
        is_in_pips = 'true' if is_in_pips else 'false'
        items = locals().items()
        params = {}
        try:
            for k, v in items:
                if k != "self":
                    params[k] = v
            return self.send("/trading/change_trade_stop_limit", params)
        except Exception as e:
            return self.__return(False, str(e))

    def change_order_stop_limit(self,
                                order_id,
                                limit,
                                stop,
                                is_limit_in_pips=False,
                                is_stop_in_pips=False):
        '''
        Creates/removes/changes the stop/limit order for the specified order.
        If the current stop/limit rate for the specified order is not set
        (is zero) and the new rate is not zero,
        then creates a new order.
        If the current stop/limit rate for the specified order is set
        (is not zero), changes order rate (if the new rate is not zero)
        or deletes order (if the new rate is zero).


        :param order_id:
        :param limit:
        :param stop:
        :param is_limit_in_pips:
        :param is_stop_in_pips:
        :return: response Dict
        '''
        items = locals().items()
        params = {}
        is_stop_in_pips = 'true' if is_buy else 'false'
        is_limit_in_pips = 'true' if is_in_pips else 'false'
        try:
            for k, v in items:
                if k != "self":
                    params[k] = v
            return self.send("/trading/change_order_stop_limit", params)
        except Exception as e:
            return self.__return(False, str(e))

    def close_all_for_symbol(self,
                             symbol,
                             account_id=None,
                             forSymbol=True,
                             order_type="AtMarket",
                             time_in_force="GTC"):
        '''
        Closes all trades for the specified account and symbol by creating net
        quantity orders, if these orders are enabled, or by creating regular
        close orders otherwise.

        :param symbol:
        :param account_id: = None (default to self.account_id)
        :param forSymbol: True/False (Default True)
        :param order_type: AtMarket / MarketRange (default AtMarket)
        :param time_in_force: IOC GTC FOK DAY GTD (default GTC)
        :return: response Dict
        '''
        items = locals().items()
        params = {}
        try:
            for k, v in items:
                if k != "self":
                    if k == 'account_id' and v is None:
                        v = self.account_id
                    params[k] = v
            return self.send("/trading/close_all_for_symbol", params)
        except Exception as e:
            return self.__return(False, str(e))

    def get_candles(self,
                    instrument,
                    period,
                    num,
                    From=None,
                    To=None,
                    dt_fmt=None):
        '''
        Allow user to retrieve candle for a given instrument at a give time

        :param instrument: instrument_id or instrument. If instrument, will
                           use mode information to convert to instrument_id
        :param period: m1, m5, m15, m30, H1, H2, H3, H4, H6, H8, D1, W1, M1
        :param num: candles, max = 10,000
        :param From: timestamp or date/time string. Will conver to timestamp
        :param To: timestamp or date/time string. Will conver to timestamp
        :param dt_fmt: Adding this optional parameter will add an additional
                       field to the candle data with the timestamp converted
                       to the datetime string provided. Example:
        .candles("USD/JPY", "m1", 3, datetime_fmt="%Y/%m/%d %H:%M:%S:%f")
        [1503694620, 109.321, 109.326, 109.326, 109.316, 109.359,
        109.358, 109.362, 109.357, 28, '2017/08/26 05:57:00:000000']
        :return: response Dict
        '''
        try:
            initial_instrument = instrument
            if not isInt(instrument):
                instrument = self.symbol_info.get(instrument,
                                                  {}).get('offerId', -1)
            if instrument < 0:
                raise ValueError("Instrument %s not found" %
                                 initial_instrument)
            if num > 10000:
                num = 10000
            params = dict(num=num)
            for k, v in {"From": From, "To": To}.items():
                if v is not None:
                    if not isInt(v):
                        v = int(time.mktime(parse(v).timetuple()))
                    params[k] = v
            candle_data = self.send("/candles/%s/%s" % (instrument, period),
                                    params, "get")
            headers = [
                'timestamp', 'bidopen', 'bidclose', 'bidhigh', 'bidlow',
                'askopen', 'askclose', 'askhigh', 'asklow', 'tickqty'
            ]
            if dt_fmt is not None:
                headers.append("datestring")
                for i, candle in enumerate(candle_data['candles']):
                    candle_data['candles'][i].append(
                        datetime.fromtimestamp(candle[0]).strftime(dt_fmt))
            candle_data['headers'] = headers
            return self.__return(candle_data['status'], candle_data)
        except Exception as e:
            return (False, str(e))

    candles = get_candles

    def candles_as_dict(self,
                        instrument,
                        period,
                        num,
                        From=None,
                        To=None,
                        dt_fmt=None):
        '''
        Allow user to retrieve candle for a given instrument at a give time
        as a dictionary.

        :param instrument: instrument_id or instrument. If instrument, will
                           use mode information to convert to instrument_id
        :param period: m1, m5, m15, m30, H1, H2, H3, H4, H6, H8, D1, W1, M1
        :param num: candles, max = 10,000
        :param From: timestamp or date/time string. Will conver to timestamp
        :param To: timestamp or date/time string. Will conver to timestamp
        :param dt_fmt: Adding this optional parameter will add an additional
                       field to the candle data with the timestamp converted
                       to the datetime string provided. Example:
        .candles("USD/JPY", "m1", 3, datetime_fmt="%Y/%m/%d %H:%M:%S:%f")
        [1503694620, 109.321, 109.326, 109.326, 109.316, 109.359,
        109.358, 109.362, 109.357, 28, '2017/08/26 05:57:00:000000']
        :return: response Dict
        '''
        try:
            candle_data = self.get_candles(instrument, period, num, From, To,
                                           dt_fmt)
            status = candle_data['status']
            if status is True:
                Headers = namedtuple('Headers', candle_data['headers'])
                candle_dict = map(Headers._make, candle_data['candles'])
                candle_data['candles'] = candle_dict
            return self.__return(status, candle_data)
        except Exception as e:
            return self.__return(False, str(e))

    def initialize(self):
        self.HEADERS = {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded',
            'User-Agent': 'request'
        }
        self.CONFIG = {}
        try:
            with open(self.config_file, 'r') as f:
                self.CONFIG = json.load(f)
        except Exception as e:
            logging.error("Error loading self.CONFIG: " + str(e))
        self.debug_level = self.CONFIG.get("DEBUGLEVEL", "ERROR")
        self.LOGLEVELS = {
            "ERROR": logging.ERROR,
            "DEBUG": logging.DEBUG,
            "INFO": logging.INFO,
            "WARNING": logging.WARNING,
            "CRITICAL": logging.CRITICAL
        }
Exemple #3
0
    print('reconnect')


def on_message_event(*args):
    for v in args:
        print('message_event:', v)


socketIO = SocketIO('localhost', 3000, LoggingNamespace)
socketIO.on('connect', on_connect)
socketIO.on('disconnect', on_disconnect)
socketIO.on('reconnect', on_reconnect)

# Listen
socketIO.on('message_event', on_message_event)
socketIO.emit('message_event', 1)
socketIO.emit('message_event', 2)
socketIO.wait(seconds=1)
#socketIO.wait()  # Use this to wait forever

# Stop listening
socketIO.off('message_event')
socketIO.emit('message_event', 3)
socketIO.wait(seconds=1)

# Listen only once
socketIO.once('message_event', on_message_event)
socketIO.emit('message_event', 4)  # Activate on_message_event
socketIO.emit('message_event', 5)  # Ignore
socketIO.wait(seconds=1)
Exemple #4
0
def on_disconnect():
    print('disconnect')

def on_reconnect():
    print('reconnect')

def on_aaa_response(*args):
    print('on_aaa_response', args)

socketIO = SocketIO('192.168.42.178', 5000, LoggingNamespace)
socketIO.on('connect', on_connect)
socketIO.on('disconnect', on_disconnect)
socketIO.on('reconnect', on_reconnect)

# Listen
socketIO.on('aaa_response', on_aaa_response)
socketIO.emit('aaa')
socketIO.emit('aaa')
socketIO.wait(seconds=1)

# Stop listening
socketIO.off('aaa_response')
socketIO.emit('aaa')
socketIO.wait(seconds=1)

# Listen only once
socketIO.once('aaa_response', on_aaa_response)
socketIO.emit('aaa')  # Activate aaa_response
socketIO.emit('aaa')  # Ignore
socketIO.wait(seconds=1)
Exemple #5
0
    global rawSequence
    rawSequence = args
    if (sequenceHasChanged(rawSequence) == True):
        newSequence = True
        print("Sequence has changed")
        #prevRawSequence = rawSequence
        global prevRawSequence
        prevRawSequence = rawSequence
        print(prevRawSequence)
        print(rawSequence)
    
#Before the first message, the Pi keeps receiving (u'[8,8,8,8]')
while (rawSequence == "(u'[8,8,8,8]')"):
    socketIO.on("sequencePi", on_a_response)
    socketIO.wait(seconds = 0.6)
    socketIO.off("sequencePi")
    
while (gameOver == False):
    socketIO.on("sequencePi", on_a_response)
    socketIO.wait(seconds=0.4)
    socketIO.off("sequencePi")
    
    if newSequence:
        #SET FROM SERVER
        recMessage = "this is purely a message"
        recSequence = ""


        if (contentIsMessage):
            #Process message and send to Arduino
            oString = "m " + recMessage + "|"
Exemple #6
0
    rawSequence = args
    if (sequenceHasChanged(rawSequence) == True):
        newSequence = True
        print("Sequence has changed")
        #prevRawSequence = rawSequence
        global prevRawSequence
        prevRawSequence = rawSequence
        print(prevRawSequence)
        print(rawSequence)


#Before the first message, the Pi keeps receiving (u'[8,8,8,8]')
while (rawSequence == "(u'[8,8,8,8]')"):
    socketIO.on("sequencePi", on_a_response)
    socketIO.wait(seconds=0.6)
    socketIO.off("sequencePi")

while (gameOver == False):
    socketIO.on("sequencePi", on_a_response)
    socketIO.wait(seconds=0.4)
    socketIO.off("sequencePi")

    if newSequence:
        #SET FROM SERVER
        recMessage = "this is purely a message"
        recSequence = ""

        if (contentIsMessage):
            #Process message and send to Arduino
            oString = "m " + recMessage + "|"
            BA = bytearray()