Ver código fonte

add REST API interface (initial version)

laxaurus 6 anos atrás
pai
commit
f9fb0a3fb1
41 arquivos alterados com 1442 adições e 325 exclusões
  1. 56 0
      requirements.txt
  2. 1 0
      src/.gitignore
  3. 254 59
      src/comms/ibgw/order_manager.py
  4. 7 1
      src/comms/ibgw/subscription_manager.py
  5. 40 11
      src/comms/ibgw/tws_event_handler.py
  6. 48 1
      src/comms/ibgw/tws_gateway.py
  7. 42 69
      src/comms/ibgw/tws_gateway_restapi.py
  8. 212 0
      src/comms/test/order_generator.py
  9. 25 0
      src/comms/test/orders.dat
  10. 4 4
      src/config/pm.cfg
  11. 8 8
      src/config/tws_gateway.cfg
  12. BIN
      src/finopt/ystockquote.pyc
  13. 111 17
      src/misc2/helpers.py
  14. 4 2
      src/misc2/observer.py
  15. 0 0
      src/omrdapi/__init__.py
  16. 243 0
      src/omrdapi/v1/apiv1.py
  17. 0 0
      src/omrdapi/v2/__init__.py
  18. 251 0
      src/omrdapi/v2/apiv2.py
  19. 123 0
      src/omrdapi/v2/quote_handler.py
  20. 0 5
      src/sh (prod)/alert.sh~
  21. 0 13
      src/sh (prod)/md_std.sh
  22. 0 13
      src/sh (prod)/md_std2.sh
  23. 0 11
      src/sh (prod)/momentum.sh
  24. 0 11
      src/sh (prod)/momentum.sh~
  25. 0 4
      src/sh (prod)/momentum2.sh
  26. 0 4
      src/sh (prod)/pairs_corr_redis.sh
  27. 0 14
      src/sh (prod)/port_stream.sh
  28. 0 4
      src/sh (prod)/portfolio.sh
  29. 0 10
      src/sh (prod)/readme.1st
  30. 0 8
      src/sh (prod)/run_mds.sh
  31. 0 4
      src/sh (prod)/run_mds.sh~
  32. 0 4
      src/sh (prod)/run_opt_serve.sh
  33. 0 4
      src/sh (prod)/run_opt_serve.sh~
  34. 0 5
      src/sh (prod)/run_options_data.sh
  35. 0 4
      src/sh (prod)/run_options_data.sh~
  36. 0 5
      src/sh (prod)/start-alert.sh
  37. 0 4
      src/sh (prod)/stop-alert.sh
  38. 0 13
      src/sh (prod)/t1.sh
  39. 0 11
      src/sh (prod)/t1.sh~
  40. 6 1
      src/sh/pm.sh
  41. 7 1
      src/sh/start_twsgw.sh

+ 56 - 0
requirements.txt

@@ -0,0 +1,56 @@
+aniso8601==6.0.0
+attrs==19.1.0
+backports.functools-lru-cache==1.5
+beautifulsoup4==4.7.1
+certifi==2019.3.9
+chardet==3.0.4
+cheroot==6.5.4
+CherryPy==13.1.0
+Click==7.0
+cycler==0.10.0
+Flask==1.0.2
+Flask-RESTful==0.3.7
+functools32==3.2.3.post2
+ib==0.8.0
+IbPy2==0.8.0
+idna==2.8
+itsdangerous==1.1.0
+jaraco.functools==2.0
+Jinja2==2.10.1
+JsonForm==0.0.2
+jsonschema==3.0.1
+JsonSir==0.0.2
+kafka==1.3.5
+kiwisolver==1.0.1
+MarkupSafe==1.1.1
+matplotlib==2.2.3
+more-itertools==5.0.0
+numpy==1.15.4
+pandas==0.23.4
+pkg-resources==0.0.0
+portend==2.4
+py==1.8.0
+py4j==0.10.7
+pyparsing==2.4.0
+pyrsistent==0.14.11
+pyspark==2.4.0
+pytest==2.6.0
+python-dateutil==2.8.0
+Python-EasyConfig==0.1.7
+pytz==2019.1
+PyYAML==5.1
+redis==2.10.6
+requests==2.21.0
+Resource==0.2.1
+scikit-learn==0.20.2
+scipy==1.2.0
+simplejson==3.16.0
+six==1.12.0
+sleekxmpp==1.3.3
+soupsieve==1.9.1
+subprocess32==3.5.3
+tempora==1.14.1
+urllib3==1.24.2
+Werkzeug==0.15.2
+wget==3.2
+ws4py==0.5.1

+ 1 - 0
src/.gitignore

@@ -0,0 +1 @@
+*.pyc

+ 254 - 59
src/comms/ibgw/order_manager.py

@@ -1,94 +1,289 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 import logging
-from time import strftime
 import json
+from time import sleep
 from misc2.helpers import ContractHelper
 from ib.ext.Contract import Contract
 from comms.ibgw.base_messaging import BaseMessageListener
 from comms.ibgw.tws_event_handler import TWS_event_handler
-from __main__ import name
-from _ast import Name
+from Queue import Queue
+import threading
+import uuid
+import numpy as np
+from finopt.test_pattern import Subscriber
 
 
 
-class OrderBook():
+class OrderIdManager(threading.Thread):
+
+    def __init__(self, tws_conn):
+        threading.Thread.__init__(self)        
+        self.id_request_q = Queue()
+        self.next_valid_q = Queue()
+        self.tws_conn = tws_conn
+        self.stop = False
+        self.tws_pending = False
+        self.clordid_id = {}
+        
+    
+    '''
+        expects a client order id of md5
+    '''        
+    def request_id(self, client_id, clordid):
+        
+        self.id_request_q.put((client_id, clordid))
+        self.id_request_q.task_done()
+        
+    ''' this function is called by tws_event_handler upon
+        receiving nextValidId reply from TWS
+    '''
+    def update_next_valid_id(self, orderId):
+        self.next_valid_q.put(orderId)
+        self.next_valid_q.task_done()
+        self.tws_pending = False
+        
+    def set_stop(self):
+        self.stop = True
+        logging.info('OrderIdManager: set stop flag to true')
+            
+    def run(self):
+        while not self.stop:
+                            
+            if not self.id_request_q.empty():
+                if not self.next_valid_q.empty():
+                    
+                    next_valid_id = self.next_valid_q.get()
+                    print 'get next valid %d next_valid_q size->%d' % (next_valid_id, self.next_valid_q.qsize())
+                    client_id, clordid = self.id_request_q.get()
+                    #
+                    # report the assigned id back to the client side
+                    self.dispatch_event('OrderRequestAck', {'client_id': client_id, 'clordid': clordid, 'next_valid_id': next_valid_id})
+                    self.clordid_id[clordid] = {'client_id': client_id, 'next_valid_id': next_valid_id}
+
+                else:
+                    #
+                    # request a next id from TWS
+                    if not self.tws_pending:
+                        self.tws_pending = True
+                        logging.info('OrderIdManager: before call to tws_conn.reqIds for the next avail id')
+                        self.tws_conn.reqIds(-1)
+                        
+                
+            # to prevent excessive CPU use
+            sleep(0.1)
+            
+    
+    def assigned_id(self, clordid):
+        try:
+            return self.clordid_id[clordid]
+        except KeyError:
+            return None
+        
+    def dispatch_event(self, event, dict):
+        logging.info ('OrderIdManager: [%s] => %s' % (event, json.dumps(dict)))
+
+
+
+class OrderIdManagerFake(threading.Thread):
+
+    def __init__(self, tws_conn):
+        threading.Thread.__init__(self)        
+        self.id_request_q = Queue()
+        self.next_valid_q = Queue()
+        self.tws_conn = tws_conn
+        self.stop = False
+        self.tws_pending = False
+        
+        #wait_th = threading.Thread(target=get_user_input, args=(response,))
+        self.fake_id = 1
+    
+    '''
+        expects a client order id of md5
+    '''        
+    def on_id_request(self, client_id, clordid):
+        
+        self.id_request_q.put((client_id, clordid))
+        self.id_request_q.task_done()
+        
+
+        
+    ''' TWS events
+    '''
+    def nextValidId(self, orderId):
+        self.next_valid_q.put(orderId)
+        self.next_valid_q.task_done()
+        self.tws_pending = False
+        
+            
+    def run(self):
+        while not self.stop:
+                            
+            if not self.id_request_q.empty():
+                print 'id_request_q size %d' % self.id_request_q.qsize()
+                if not self.next_valid_q.empty():
+                    
+                    next_valid_id = self.next_valid_q.get()
+                    print 'get next valid %d next_valid_q size->%d' % (next_valid_id, self.next_valid_q.qsize())
+                    client_id, clordid = self.id_request_q.get()
+                    #
+                    # dispatch ?
+                    self.dispatch_event('OrderRequestAck', {'client_id': client_id, 'clordid': clordid, 'next_valid_id': next_valid_id})
+
+                else:
+                    #
+                    # request a next id from TWS
+                    if not self.tws_pending:
+                        self.tws_pending = True
+                        #self.tws_conn.reqIds(-1)
+                        self.fake_gen_id()
+                
+            # to prevent excessive CPU use
+            sleep(0.1)
+            
+            
+    def fake_gen_id(self):
+        print 'fake id %d' % self.fake_id
+        sleep(0.4)
+        self.nextValidId(self.fake_id)
+        self.fake_id+=1
+        
+    def dispatch_event(self, event, dict):
+        #logging.info('OrderIdManager: [%s] => %s', (event, json.dumps(dict)))
+        print 'OrderIdManager: [%s] => %s' % (event, json.dumps(dict))
+    
+
+class OrderBook(Subscriber):
     
     def __init__(self, name):
         '''
             orderbook:
-                contains orders which is a dict that maps tws orderId 
-                each order has an order_status map
-                each order has an order_status_hist which is a list to previous order_status
-                each order has an exec_status_hist which is a list of executions
+ 
             
                 
         '''
+        Subscriber.__init__(self, name)
         self.name = name 
         self.orders = {}
         
-    def update_order_status(self, orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld):
-        if orderId in self.orders:
-            self.orders[orderId]['order_status']['status'] = status
-            self.orders[orderId]['order_status']['filled'] = filled
-            self.orders[orderId]['order_status']['remaining'] = remaining
-            self.orders[orderId]['order_status']['avgFillPrice'] = avgFillPrice
-            self.orders[orderId]['order_status']['permId'] = permId
-            self.orders[orderId]['order_status']['parentId'] = parentId
-            self.orders[orderId]['order_status']['lastFillPrice'] = lastFillPrice
-            self.orders[orderId]['order_status']['clientId'] = clientId
-            self.orders[orderId]['order_status']['whyHeld'] = whyHeld
-        else:
-            logging.warn('OrderBook:update_order_status. orderId %d key not found in the dict.' % orderId)
+    def handle_order_status(self, orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld):
+        try:
+            _ = self.orders[orderId]
+        except KeyError:
+            self.orders[orderId]= {'ord_status':{}, 'error':{}, 'order':{}, 'contract': {}}
+             
+        self.orders[orderId]['ord_status']['status'] = status
+        self.orders[orderId]['ord_status']['filled'] = filled
+        self.orders[orderId]['ord_status']['remaining'] = remaining
+        self.orders[orderId]['ord_status']['avgFillPrice'] = avgFillPrice
+        self.orders[orderId]['ord_status']['permId'] = permId
+        self.orders[orderId]['ord_status']['parentId'] = parentId
+        self.orders[orderId]['ord_status']['lastFillPrice'] = lastFillPrice
+        self.orders[orderId]['ord_status']['clientId'] = clientId
+        self.orders[orderId]['ord_status']['whyHeld'] = whyHeld
+    
+    def handle_error(self, id, errorCode, errorMsg):
+        try:
+            _ = self.orders[id]
+        except KeyError:        
+            self.orders[id]= {'ord_status':{}, 'error':{}, 'order':{}, 'contract': {}}
+            
+        self.orders[id]['error'] = {'errorCode': errorCode, 'errorMsg': errorMsg}
         
-
+    def handle_open_order(self, orderId, state, order, contract):
+        try:
+            _ = self.orders[orderId]
+        except KeyError:
+            self.orders[orderId]= {'ord_status':{}, 'error':{}, 'order':{}, 'contract': {}} 
+        self.orders[orderId]['order'] = order
+        self.orders[orderId]['contract'] = contract
+        
+    def update(self, event, **param): 
+        if event == 'orderStatus':
+            self.handle_order_status(**param)
+        elif event == 'openOrder':
+            self.handle_open_order(**param)
+        elif event == 'openOrderEnd':
+            pass
+        elif event == 'error':
+            try:
+                id = param['id']
+                if id <> -1:
+                    self.handle_error(**param)
+            except:
+                logging.error('OrderBook ERROR: in processing tws error event %s' % param)
+                return
+    
+    def get_order_status(self, orderId):
+        try:
+            orderId = int(orderId)
+            return self.orders[orderId]
+        except:
+            return None
+          
+'''
+    client side order manager
+'''
 class OrderManager(BaseMessageListener):
     
-    def __init__(self, name, tws_connection, producer, rs_conn, kwargs):
+    def __init__(self, name, gw_parent, kwargs):
         self.name = name
-        self.tws_connect = tws_connection
+        self.gw_parent = gw_parent
+        self.tws_connect = self.gw_parent.get_tws_connection()
+        self.tws_event_handler = gw_parent.get_tws_event_handler()
         self.order_book = OrderBook(self.name)
-        self.order_id = self.load_order_id()
+
+        self.order_id_mgr = OrderIdManager(self.tws_connect)
+        self.tws_event_handler.set_order_id_manager(self.order_id_mgr)
         
         
-    def load_order_id(self):
-        return -1
-    
-    def get_next_order_id(self):
-        self.order_id = self.order_id + 1
-        return self.order_id
-    
+        '''
+             ask tws_event_handler to forward order messages to
+             the order_book class
+        '''
+        for e in TWS_event_handler.PUBLISH_TWS_EVENTS:
+            self.tws_event_handler.register(e, self.order_book)        
+        
     
-    def place_order(self, event, client_order_id, contract_key, side, quantity, price):
-        logging.info('OrderManager:place_order. client_order_id %d, contract %s, side %s, qty %d, price %8.2f' %
-                            (client_order_id, contract_key, side, quantity, price))
-
+    def start_order_manager(self):
+        self.order_id_mgr.start()
         '''
-            insert a new entry into the orderbook
-            get the next order id
-            submit order request to tws
+            
+            rebuild order book
+            **** 
+             
+             persitence function missing!!
+             to be implemented
+            
         '''
-
-                            
-        try:
-            vals = json.loads(value)
-        except ValueError:
-            logging.error('TWS_gateway - placeOrder Exception %s' % traceback.format_exc())
-            return
-        
-    #        c = ContractHelper.kvstring2contract(vals[1])
-        o = OrderHelper.kvstring2object(vals[2], Order)
-        o.__dict__['transmit'] = self.ib_order_transmit
-    #         print c.__dict__
-    #         print o.__dict__
-    #         print '---------------------'
-    
-           
-        #self.connection.placeOrder(vals[0], ContractHelper.kvstring2contract(vals[1]), OrderHelper.kvstring2object(vals[2], Order))
-        self.tws_connect.placeOrder(vals[0], ContractHelper.kvstring2object(vals[1], Contract), OrderHelper.kvstring2object(vals[2], Order))
-    #        self.connection.placeOrder(orderId, contract, newOptOrder)
+        self.tws_connect.reqOpenOrders()
+        logging.info('OrderManager: start_order_manager: request open orders')
         
+    
+    def get_order_id_mgr(self):
+        return self.order_id_mgr
+    
+    
+    def get_order_book(self):
+        return self.order_book
+    
+    def is_id_in_order_book(self, id):
+        if self.get_order_book().get_order_status(id):
+            return True
+        return False
+      
+if __name__ == '__main__':
+    
+    oim = OrderIdManagerFake(1)
 
+    def do_stuff(client):
+        for i in range(10):
+            oim.on_id_request(client, str(uuid.uuid4()))
+            sleep(np.random.uniform(0, 1) * 0.5)
     
-        
+    for j in range(2):
+        threading.Thread(target=do_stuff, args=(['client%d'% j])).start()
+        #sleep(2)        
+    
+    oim.start()
         

+ 7 - 1
src/comms/ibgw/subscription_manager.py

@@ -161,7 +161,13 @@ class SubscriptionManager(BaseMessageListener):
         return id
 
             
-    #def reqMktData(self, event, message):
+    '''
+     this function gets called whenever a client request for market data
+     check the line below at tws_gateway __init__
+     
+         self.gw_message_handler.add_listener_topics(self.contract_subscription_mgr, self.kwargs['subscription_manager.topics'])
+         
+    ''' 
     def reqMktData(self, event, contract, snapshot):        
                   
 #         contract = ContractHelper.kvstring2object(message['contract'], Contract)

+ 40 - 11
src/comms/ibgw/tws_event_handler.py

@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-from misc2.helpers import ContractHelper, ExecutionHelper
+from misc2.helpers import ContractHelper, ExecutionHelper, OrderHelper, OrderStateHelper
+from misc2.observer import Publisher
 import logging
 import traceback
 from ib.ext.EWrapper import EWrapper
@@ -8,15 +9,28 @@ import json
 
 
         
-class TWS_event_handler(EWrapper):
+class TWS_event_handler(EWrapper, Publisher):
 
     TICKER_GAP = 1000
     producer = None
     
-    def __init__(self, producer):        
+    # Events that will get forwarded to 
+    # any classes that is interested in listening
+    # WebConsole is one such subscriber
+    # it is interested in 
+    PUBLISH_TWS_EVENTS = ['error', 'openOrder', 'openOrderEnd', 'orderStatus', 'openBound', 'tickPrice', 'tickSize']
+    
+    def __init__(self, producer):
         self.producer = producer
+
+        # create an internal publisher to forward tws messages 
+        # to WebConsole class                
+        Publisher.__init__(self, TWS_event_handler.PUBLISH_TWS_EVENTS)
         
- 
+    
+    
+    def set_order_id_manager(self, order_id_manager):
+        self.order_id_manager = order_id_manager
  
     def set_subscription_manager(self, subscription_manager):
         self.subscription_manger = subscription_manager
@@ -26,7 +40,12 @@ class TWS_event_handler(EWrapper):
         try:
             dict = self.pre_process_message(message, mapping)     
             logging.debug('broadcast_event %s:%s' % (message, dict))
-            self.producer.send_message(message, self.producer.message_dumps(dict))    
+            self.producer.send_message(message, self.producer.message_dumps(dict))   
+            
+            # forward message to subscribed consumers,
+            # that is webconsole
+            if message in self.PUBLISH_TWS_EVENTS:
+                self.dispatch(message, dict) 
         except:
             logging.error('broadcast_event: exception while encoding IB event to client:  [%s]' % message)
             logging.error(traceback.format_exc())
@@ -95,15 +114,22 @@ class TWS_event_handler(EWrapper):
         #self.broadcast_event('tickEFP', vars())
         pass
 
-    def orderStatus(self, orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeId):
-        pass
+    def orderStatus(self, orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld):
+        self.broadcast_event('orderStatus', {'orderId':orderId, 'status': status, 'filled':filled, 
+                                             'remaining':remaining, 'avgFillPrice':avgFillPrice, 
+                                             'permId':permId, 'parentId':parentId, 'lastFillPrice':lastFillPrice, 
+                                             'clientId':clientId, 'whyHeld':whyHeld})
 
     def openOrder(self, orderId, contract, order, state):
-        pass
+        logging.info('TWS_event_handler: openOrder id:%d contract:%s' % (orderId, ContractHelper.makeRedisKey(contract)))
+        logging.info('TWS_event_handler: openOrder order:%s' % (OrderHelper.object2kvstring(order)))
+        logging.info('TWS_event_handler: openOrder state: %s' % (OrderStateHelper.object2kvstring(state)))
+        self.broadcast_event('openOrder', {'orderId': orderId, 'contract':contract, 'order':order, 'state':state})
+        
 
     def openOrderEnd(self):
-        pass
-
+        logging.info('TWS_event_handler: openOrderEnd')
+        self.broadcast_event('openOrderEnd', {})
 
     def update_portfolio_account(self, items):
         self.broadcast_event('update_portfolio_account', items)
@@ -149,7 +175,10 @@ class TWS_event_handler(EWrapper):
         
         
     def nextValidId(self, orderId):
-        self.broadcast_event('nextValidId', vars())
+        #self.broadcast_event('nextValidId', orderId)
+        self.order_id_manager.update_next_valid_id(orderId)
+        logging.info('TWS_event_handler:nextValidId %d' % orderId)
+        
 
     def contractDetails(self, reqId, contractDetails):
         self.broadcast_event('contractDetails', vars())

+ 48 - 1
src/comms/ibgw/tws_gateway.py

@@ -19,10 +19,14 @@ from comms.ibgw.client_request_handler import ClientRequestHandler
 from comms.ibgw.subscription_manager import SubscriptionManager
 from comms.tws_protocol_helper import TWS_Protocol
 from comms.ibgw.tws_gateway_restapi import WebConsole 
+from comms.ibgw.order_manager import OrderManager
+from omrdapi.v2.quote_handler import QuoteRESTHandler
 import redis
 import threading
 from threading import Lock
          
+                   
+         
 class TWS_gateway():
 
     
@@ -69,6 +73,7 @@ class TWS_gateway():
             3. establish TWS gateway connectivity
             
             4. initialize listeners: ClientRequestHandler and SubscriptionManager
+            4a. start order_id_manager
             5. start the prosumer 
             6. run web console
         
@@ -85,6 +90,7 @@ class TWS_gateway():
         logging.info('starting up gateway message handler - kafka Prosumer...')        
         self.gw_message_handler = Prosumer(name='tws_gw_prosumer', kwargs=self.kwargs)
         
+        
         logging.info('initializing TWS_event_handler...')        
         self.tws_event_handler = TWS_event_handler(self.gw_message_handler)
         
@@ -119,6 +125,11 @@ class TWS_gateway():
         self.gw_message_handler.add_listeners([self.cli_req_handler])
         self.gw_message_handler.add_listener_topics(self.contract_subscription_mgr, self.kwargs['subscription_manager.topics'])
 
+        logging.info('initialize order_id_manager and quote_handler for REST API...')
+        self.initialize_order_quote_manager()
+        
+
+
         logging.info('start TWS_event_handler. Start prosumer processing loop...')
         self.gw_message_handler.start_prosumer()
 
@@ -140,6 +151,17 @@ class TWS_gateway():
         
         self.tws_event_handler.set_subscription_manager(self.contract_subscription_mgr)
 
+
+    def initialize_order_quote_manager(self):
+#         self.order_id_mgr = OrderIdManager(self.tws_connection)
+#         self.tws_event_handler.set_order_id_manager(self.order_id_mgr)
+#         self.order_id_mgr.start()
+          self.order_manager = OrderManager('order_manager', self, self.kwargs)
+          self.order_manager.start_order_manager()
+          
+          
+          self.quote_manager = QuoteRESTHandler('quote_manager', self)
+        
     def initialize_redis(self):
 
         self.rs = redis.Redis(self.kwargs['redis_host'], self.kwargs['redis_port'], self.kwargs['redis_db'])
@@ -156,6 +178,12 @@ class TWS_gateway():
         
         def start_flask():
             w = WebConsole(self)
+            
+            # tell tws_event_handler that WebConsole  
+            # is interested to receive all messages
+            for e in TWS_event_handler.PUBLISH_TWS_EVENTS:
+                self.tws_event_handler.register(e, w)
+            
             w.add_resource()
             w.app.run(host=self.kwargs['webconsole.host'], port=self.kwargs['webconsole.port'],
                       debug=self.kwargs['webconsole.debug'], use_reloader=self.kwargs['webconsole.auto_reload'])
@@ -164,8 +192,25 @@ class TWS_gateway():
         t_webApp.setDaemon(True)
         t_webApp.start()
                 
+                
+    def get_order_id_manager(self):
+        return self.order_manager.get_order_id_mgr()
 
-            
+    def get_order_manager(self):
+        return self.order_manager
+    
+    def get_tws_connection(self):
+        return self.tws_connection
+    
+    def get_tws_event_handler(self):
+        return self.tws_event_handler
+    
+    def get_subscription_manager(self):
+        return self.contract_subscription_mgr
+    
+    def get_quote_manager(self):
+        return self.quote_manager
+    
     def get_redis_conn(self):
         return self.rs
 
@@ -227,6 +272,7 @@ class TWS_gateway():
         self.gw_message_handler.join()
         self.ibh.shutdown()
         self.menu_loop_done = True
+        self.get_order_id_manager().set_stop()
         sys.exit(0)
         
 
@@ -312,6 +358,7 @@ if __name__ == '__main__':
     
     (options, args) = parser.parse_args()
     
+    
     kwargs = ConfigMap().kwargs_from_file(options.config_file)
     for option, value in options.__dict__.iteritems():
         

+ 42 - 69
src/comms/ibgw/tws_gateway_restapi.py

@@ -1,90 +1,63 @@
-from flask import Flask
-from flask_restful import Resource, Api, reqparse
+from flask import Flask, jsonify
+
 import json
 import threading
-import time
-from cheroot.server import Gateway
-import sys
+from time import sleep
+from misc2.helpers import ContractHelper, OrderHelper, OrderValidationException
+from misc2.observer import Subscriber
+from flask_restful import Resource, Api, reqparse
+import uuid
+import traceback
+from omrdapi.v1 import apiv1
+from omrdapi.v2 import apiv2
+
+
 
 
-class WebConsole():
+class WebConsole(Subscriber):
 
+    
     app = Flask(__name__)
     api = Api(app)
     parser = reqparse.RequestParser()
     
     def __init__(self, parent=None):
+        Subscriber.__init__(self, 'WebConsole' )
         self.parent = parent
+        self.id_message = {}
 
     def get_parent(self):
         return self.parent
     
     def add_resource(self):
-        WebConsole.api.add_resource(Commands, '/')
-        WebConsole.api.add_resource(ExitApp, '/exit', resource_class_kwargs={'gateway_instance': self.parent})
-        WebConsole.api.add_resource(Subscriptions, '/subscriptions', resource_class_kwargs={'gateway_instance': self.parent})
-        WebConsole.api.add_resource(GatewaySettings, '/settings', resource_class_kwargs={'gateway_instance': self.parent})
-        
-
-class Commands(Resource):
-    def get(self):
-        return {'status': True, 'Available REST API' : {'exit': 'shutdown gateway', 
-                                              'subscriptions': 'get a list of subscribed topics',
-                                              'settings': 'get gateway startup settings',
-                                              
-                                              }
-                }
-
-class ExitApp(Resource):
-    def __init__(self, gateway_instance):
-        self.gw = gateway_instance
+        WebConsole.api.add_resource(apiv1.Commands, '/v1')
+        WebConsole.api.add_resource(apiv1.ExitApp, '/v1/exit', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv1.Subscriptions, '/v1/subscriptions', resource_class_kwargs={'gateway_instance': self.parent})
+        WebConsole.api.add_resource(apiv1.GatewaySettings, '/v1/settings', resource_class_kwargs={'gateway_instance': self.parent})
+        WebConsole.api.add_resource(apiv1.AsyncOrderCRUD, '/v1/async_order/<id>', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv1.SyncOrderCRUD, '/v1/order', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv1.OrderId, '/v1/order_id', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv1.OrderStatus, '/v1/order_status/<id>', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv1.OpenOrdersStatus, '/v1/open_orders', resource_class_kwargs={'webconsole': self})
         
-    def get(self):
-        self.gw.post_shutdown()
-        return {'status': 'please check the log for exit status'}
         
+        WebConsole.api.add_resource(apiv2.SyncOrderCRUD_v2, '/v2/order', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv2.OrderStatus_v2, '/v2/order_status/<id>', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv2.OpenOrdersStatus_v2, '/v2/open_orders', resource_class_kwargs={'webconsole': self})
+        WebConsole.api.add_resource(apiv2.QuoteRequest_v2, '/v2/quote', resource_class_kwargs={'webconsole': self})
 
-class GatewaySettings(Resource):
-    def __init__(self, gateway_instance):
-        self.gw = gateway_instance
-        
-    def get(self):
-        return json.loads(json.dumps(self.gw.kwargs))
-    
-    
-
-    
 
 
-class Subscriptions(Resource):
-    def __init__(self, gateway_instance):
-        self.gw = gateway_instance
-    
-    def get(self):
-        idc = self.gw.contract_subscription_mgr.get_id_contracts()
-        c2id = self.gw.contract_subscription_mgr.idContractMap['contract_id']
-        return {'status': True, 'subscriptions' : {'id2c': idc, 'c2id': c2id}}
-
-
-# def start_flask():
-#     w = WebConsole()
-#     w.add_resource()
-#     w.app.run(debug=True, use_reloader=False)
-# 
-# if __name__ == '__main__':
-#     
-#     
-#     
-#     t_webApp = threading.Thread(name='Web App', target=start_flask)
-#     t_webApp.setDaemon(True)
-#     t_webApp.start()
-#     
-#     try:
-#         while True:
-#             print 'sleeping...'
-#             time.sleep(1)
-#     
-#     except KeyboardInterrupt:
-#         print("exiting")
-#         exit(0)    
-#     
+        
+    def post_shutdown(self):
+        self.parent.post_shutdown() 
+    '''
+        implement the consumer interface
+        this function gets all tws events
+        forwarded internally from tws_event_handler
+    '''
+    def update(self, event, **param):
+        if event == 'error':
+            print ('webconsole override %s: %s %s %s' % (self.name, event, "<empty param>" if not param else param,
+                                          
+                                         '<none>' if not param else param.__class__))

+ 212 - 0
src/comms/test/order_generator.py

@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import logging
+import json
+import threading
+import sys
+from misc2.helpers import ContractHelper, ConfigMap, OrderHelper
+from optparse import OptionParser
+import requests
+import traceback
+
+
+order_function = {
+                    'LMT': OrderHelper.limit_order,
+                    'MKT': OrderHelper.market_order,
+                    'LIT': OrderHelper.limit_if_touched,
+                    'STP LMT': OrderHelper.stop_limit
+                } 
+
+def read_dat_v1(path, mode, url ):
+    results = []
+    f = open(path)
+    lns = f.readlines()
+    lns = filter(lambda l: l[0] <> '#' and l[0] <> '\n', lns)
+    for l in lns:
+        #print l
+        CO =  l.split('|')
+        C_tok = CO[0]
+        O_tok = CO[1]
+        
+        vals = C_tok.split(':')
+        contract = [None, None, None, None, None, None, None]
+        read_vals = list(eval(vals[1]))
+        contract = read_vals + contract[len(read_vals):]
+        print contract
+        c = ContractHelper.makeContract(tuple(contract))
+        cs = ContractHelper.contract2kvstring(c)
+        
+        vals = O_tok.split(':')
+            
+        def format_val(v):
+            try:           
+                if '.' in v:        
+                    return float(v)
+                else:
+                    return int(v)
+            except ValueError:
+                return v.replace("'", "").replace("\n","").replace(" ", "")
+            
+        toks = map(format_val, vals[1].split(','))
+        f = order_function[toks[0]]
+        args = toks[1:]
+        order = f(*args)
+        os =  OrderHelper.order2kvstring(order)
+        if mode == 'sync':
+            results.append(url % (cs, os))
+        
+    
+    return results   
+
+
+def format_contract_to_v2_str(contract):
+    
+    mmap = {"m_symbol": "symbol", "m_secType": "sec_type",  
+     "m_right": "right", "m_expiry": "expiry", 
+     "m_currency": "currency", "m_exchange": "exchange", "m_strike": 'strike'}
+    
+    cdict = {}
+    for k,v in contract.__dict__.iteritems():
+        if k in mmap and v <> None:
+             cdict[mmap[k]] = v
+    return json.dumps(cdict)
+
+def format_order_to_v2_str(order):
+    omap = {'m_orderType': 'order_type',
+            'm_account': 'account', 'm_action': 'side',
+            'm_totalQuantity': 'quantity', 
+            'm_lmtPrice':  'price',
+            'm_auxPrice': 'aux_price'
+            }
+    odict = {}
+    for k,v in order.__dict__.iteritems():
+        if k in omap and v <> None:
+             odict[omap[k]] = v
+    return json.dumps(odict)
+    
+
+def read_dat_v2(path, mode, url, version_digit ):
+    results = []
+    f = open(path)
+    lns = f.readlines()
+    lns = filter(lambda l: l[0] <> '#' and l[0] <> '\n', lns)
+    for l in lns:
+        #print l
+        CO =  l.split('|')
+        C_tok = CO[0]
+        O_tok = CO[1]
+        
+        vals = C_tok.split(':')
+        contract = [None, None, None, None, None, None, None]
+        read_vals = list(eval(vals[1]))
+        contract = read_vals + contract[len(read_vals):]
+        c = ContractHelper.makeContract(tuple(contract))
+        del c.__dict__['m_includeExpired']
+        print c.__dict__
+        
+        cs = format_contract_to_v2_str(c)
+        
+        vals = O_tok.split(':')
+            
+        def format_val(v):
+            try:           
+                if '.' in v:        
+                    return float(v)
+                else:
+                    return int(v)
+            except ValueError:
+                return v.replace("'", "").replace("\n","").replace(" ", "")
+            
+        toks = map(format_val, vals[1].split(','))
+        f = order_function[toks[0]]
+        args = toks[1:]
+        order = f(*args)
+        os =  format_order_to_v2_str(order)
+        
+        
+        if mode == 'sync':
+            results.append(url % (version_digit, cs, os))
+        
+    
+    return results   
+
+
+
+def api_post(url):
+
+    try:
+        
+        response = requests.post(url) #, data=json.loads(name))
+        return response.text
+    except:
+        return "invalid input. Check your json request string. %s" % traceback.format_exc()
+            
+    
+
+def api_delete(url):
+    try:
+        
+        response = requests.delete(url) #, data=json.loads(name))
+        return response.text
+    except:
+        return "invalid input. Check your json request string. %s" % traceback.format_exc()
+
+    
+if __name__ == '__main__':
+
+    kwargs = {
+                'logconfig': {'level': logging.INFO},
+                'mode': 'sync',
+                'url': 'http://localhost:5001/v%s/order?contract=%s&order_condition=%s'
+              }
+    
+    usage = "usage: %prog [options]"
+    parser = OptionParser(usage=usage)
+    
+    parser.add_option("-f", "--dat_file",
+                      action="store", dest="dat_file", 
+                      help="path to the dat file")
+    parser.add_option("-t", "--test_case",
+                      action="store", dest="case_no", 
+                      help="test case no: 1 = generate new order json only, 2= generate + send")
+    parser.add_option("-v", "--version",
+                      action="store", dest="version", 
+                      )
+    parser.add_option("-x", "--delete_id",
+                      action="store", dest="del_ids", 
+                      )
+    
+    
+    (options, args) = parser.parse_args()
+    if not options.case_no:
+        parser.error('-t option not specified. specify -t 1 or -t 2. ')
+    if not options.version:
+        parser.error('-v version number either 1 or 2')
+
+    
+    for option, value in options.__dict__.iteritems():
+    
+        if value <> None:
+            kwargs[option] = value
+
+    
+    logconfig = kwargs['logconfig']
+    logconfig['format'] = '%(asctime)s %(levelname)-8s %(message)s'    
+    logging.basicConfig(**logconfig)        
+
+    logging.info('config settings: %s' % kwargs)
+    
+    if kwargs['version'] == '1':
+        results= read_dat_v1(kwargs['dat_file'], kwargs['mode'], kwargs['url'], kwargs['version'])
+    else:
+        results= read_dat_v2(kwargs['dat_file'], kwargs['mode'], kwargs['url'], kwargs['version'])
+    if kwargs['case_no'] == '1':
+        print '\n'.join(s for s in results)
+    elif kwargs['case_no'] == '2':
+        for r in results:
+            print api_post(r)
+    elif kwargs['case_no'] == '3':
+        url = 'http://localhost:5001/v2/order?id=%s'
+        ids = kwargs['del_ids'].split(',')
+        map(lambda x:api_delete(url % x), ids)
+

+ 25 - 0
src/comms/test/orders.dat

@@ -0,0 +1,25 @@
+# 
+# contract tuple
+#	symbol, sectype, exchange, currency, expiry, strike, right 
+#
+# order instruction
+# 	order type,account,side,quantity,price,aux_price
+#
+# each line:
+# C:(contract tuple)|O:order instruction
+
+C:('HSI','FUT','HKFE','HKD','20190429',0,'')|O:'LMT','U9050568','BUY',1,28000
+C:('HSI','OPT','HKFE','HKD','20190429',28200,'P')|O:'LMT','U9050568','BUY',1,2
+#
+# 
+C:('GBP','CASH','IDEALPRO','USD')|O:'MKT','DU1460682', 'BUY', 100000, 1.2986
+C:('GBP','CASH','IDEALPRO','USD')|O:'LMT','DU1460682', 'BUY', 100000, 1.1986
+C:('USD','CASH','IDEALPRO','JPY')|O:'LMT','DU1460682', 'SELL', 100000, 119.55
+C:('BA','STK','SMART','USD')|O:'LMT','DU1460682', 'SELL', 100, 380.5
+C:('TSLA','STK','SMART','USD')|O:'MKT','DU1460682', 'SELL', 100, 0
+C:('TSLA', 'OPT', 'SMART', 'USD', '20190426', 270.0, 'C')|O:'MKT','DU1460682', 'SELL', 8, 0 
+#
+# invalid stock code
+# 
+C:('BAF55','STK','SMART','USD')|O:'LMT','DU1460682', 'SELL', 100, 380.5
+C:('USD.JJJ','CASH','IDEALPRO','JPY')|O:'LMT','DU1460682', 'SELL', 100000, 119.55

+ 4 - 4
src/config/pm.cfg

@@ -1,11 +1,11 @@
 [portfolio_monitor]
 name: 'portfolio_monitor'
-bootstrap_host: 'vorsprung'
+bootstrap_host: 'localhost'
 bootstrap_port: 9092
 redis_host: 'localhost'
-redis_port: 6379
-redis_db: 0
-tws_host: 'vsu-longhorn'
+redis_port: 8379
+redis_db: 2
+tws_host: 'localhost'
 group_id: 'PM'
 session_timeout_ms: 10000
 clear_offsets:  False

+ 8 - 8
src/config/tws_gateway.cfg

@@ -3,24 +3,24 @@ name: 'tws_gateway_server'
 #
 # kafka settings
 #
-bootstrap_host: 'vorsprung'
+bootstrap_host: 'localhost'
 bootstrap_port: 9092
 #
 # redis persistence
 #
 redis_host: 'localhost'
-redis_port: 6379
+redis_port: 8379
 #
 # DIFFERENT REDIS DB for PRODUCTION == 1 ELSE 0!!!
-redis_db: 0
+redis_db: 2
 #
 # TWS gateway settings
 #
-# 7496 - production larry046, 7496 - development,  8496 production mchan927
+# paper trade - 7497
 #
-tws_host: 'vsu-longhorn'
-tws_api_port: 8496
-tws_app_id: 5567
+tws_host: 'localhost'
+tws_api_port: 7497
+tws_app_id: 6567
 #
 #
 #
@@ -41,7 +41,7 @@ reset_db_subscriptions: False
 #
 ib_heartbeat.ib_port: 8496
 ib_heartbeat.appid.id: 9911
-ib_heartbeat.gateway: 'vsu-longhorn'
+ib_heartbeat.gateway: 'localhost'
 ib_heartbeat.try_interval: 60
 ib_heartbeat.suppress_msg_interval: 120
 #

BIN
src/finopt/ystockquote.pyc


+ 111 - 17
src/misc2/helpers.py

@@ -7,9 +7,11 @@ import threading
 import ConfigParser
 from ib.ext.Contract import Contract
 from ib.ext.Order import Order
+from ib.ext.OrderState import OrderState
 from ib.ext.Execution import Execution
 from ib.ext.ExecutionFilter import ExecutionFilter
 import copy
+from flask_restful.fields import Price
 
 
 class BaseHelper():
@@ -29,24 +31,109 @@ class BaseHelper():
         map(lambda x: o.__setattr__(x, kv[x].encode('ascii') if type(kv[x]) == unicode else kv[x]), kv.keys())
         return o
         
+class OrderValidationException(Exception):
+    pass    
         
 class OrderHelper(BaseHelper):
+    
+    @staticmethod
+    def order_validation(account, side, quantity, price):
+        if account == None or account == '':
+            raise OrderValidationException("account must not be blank!")
+        elif str(side) not in ['BUY', 'SELL']:
+            raise OrderValidationException("side must be either 'BUY' or 'SELL'")
+        elif quantity == None or type(quantity) == 'str':
+            raise OrderValidationException("quantity must be an integer")
+        elif '.' in str(quantity):
+            raise OrderValidationException("quantity can not be a float")
+        elif price == None or type(price) == 'str':
+            raise OrderValidationException("price must be a float")
+        
+        try:
+            int(quantity)
+            float(price)
+        except ValueError:
+            raise OrderValidationException("price or quantity must be a numeric value")
+        
+        return True
+        
+        
+    @staticmethod
+    def order_validation_ex(order):
+        if order.m_orderType == None:
+            raise OrderValidationException("order type must not be blank")
+        elif order.m_orderType in ['LMT', 'STP LMT']:
+            OrderHelper.order_validation(order.m_account, order.m_action, order.m_totalQuantity, order.m_lmtPrice)
+        elif order.m_orderType =='MKT':
+            OrderHelper.order_validation(order.m_account, order.m_action, order.m_totalQuantity, 0.0)
+        
+            
+        
+    @staticmethod
+    def order2kvstring(order):
+        return json.dumps(order.__dict__)     
+  
+    @staticmethod
+    def kvstring2object(sm_order):
+        return OrderHelper.kv2object(json.loads(sm_order))
+  
+  
+    @staticmethod
+    def kv2object(m_order):   
+        newOrder = Order()
+        map(lambda x: newOrder.__setattr__(x, m_order[x].encode('ascii') if type(m_order[x]) == unicode else m_order[x]), m_order.keys())
+        return newOrder
+
+    @staticmethod
+    def limit_order(account=None, side=None, quantity=None, price=None):
+        OrderHelper.order_validation(account, side, quantity, price)
+        newOrder = Order()
+        newOrder.m_account = account
+        newOrder.m_action = side
+        newOrder.m_totalQuantity = quantity
+        newOrder.m_lmtPrice = price  
+        newOrder.m_orderType = 'LMT'
+        return newOrder
+        
+    @staticmethod
+    def market_order(account=None, side=None, quantity=None, price=None):
+        OrderHelper.order_validation(account, side, quantity, 0.0)
+        newOrder = Order()
+        newOrder.m_account = account
+        newOrder.m_action = side
+        newOrder.m_totalQuantity = quantity
+        newOrder.m_orderType = 'MKT'
+        return newOrder
+        
+    @staticmethod
+    def limit_if_touched(account=None, side=None, quantity=None, limit_price=None, aux_price=None):
+        OrderHelper.order_validation(account, side, quantity, limit_price)
+        newOrder = Order()
+        newOrder.m_account = account
+        newOrder.m_action = side
+        newOrder.m_totalQuantity = quantity
+        newOrder.m_lmtPrice = limit_price
+        newOrder.m_auxPrice = aux_price
+        newOrder.m_orderType = 'LIT'
+        return newOrder  
+
+    @staticmethod
+    def stop_limit(account=None, side=None, quantity=None, limit_price=None, stop_price=None):
+        OrderHelper.order_validation(account, side, quantity, limit_price)
+        newOrder = Order()
+        newOrder.m_account = account
+        newOrder.m_action = side
+        newOrder.m_totalQuantity = quantity
+        newOrder.m_lmtPrice = limit_price
+        newOrder.m_auxPrice = stop_price  
+        newOrder.m_orderType = 'STP LMT'
+        return newOrder
+
+
+  
+
+class OrderStateHelper(BaseHelper):
     pass
-     
-#     @staticmethod
-#     def object2kvstring(contract):
-#         return json.dumps(contract.__dict__)
-#  
-#     @staticmethod
-#     def kvstring2object(sm_order):
-#         return OrderHelper.kv2object(json.loads(sm_order))
-#  
-#  
-#     @staticmethod
-#     def kv2object(m_order):   
-#         newOrder = Order()
-#         map(lambda x: newOrder.__setattr__(x, m_order[x].encode('ascii') if type(m_order[x]) == unicode else m_order[x]), m_order.keys())
-#         return newOrder
 
     
 class ExecutionFilterHelper(BaseHelper):
@@ -115,7 +202,8 @@ class ExecutionHelper(BaseHelper):
 
 class ContractHelper(BaseHelper):
     
-    map_rules = {'exchange': {'HSI': 'HKFE', 'MHI': 'HKFE'}}
+    map_rules = {'exchange': {'HSI': 'HKFE', 'MHI': 'HKFE'},
+                 'secType': {'CASH': 'IDEALPRO'}}
     
     def __init__(self, contractTuple):
         self.makeContract(contractTuple)
@@ -251,7 +339,13 @@ class ContractHelper(BaseHelper):
         try:
             contract.m_exchange = ContractHelper.map_rules['exchange'][contract.m_symbol]
         except:
-            contract.m_exchange = '' 
+            
+            if 'CASH' in contract.m_secType:
+                pass
+            elif 'USD' in contract.m_currency and 'SMART' in contract.m_exchange:
+                pass 
+            else:
+                contract.m_exchange = '' 
             
         
 

+ 4 - 2
src/misc2/observer.py

@@ -14,6 +14,7 @@ class Subscriber:
     def __init__(self, name):
         self.name = name
 
+    
     def update(self, event, param=None):
         #print('{} got message "{}"'.format(self.name, message))
         raise NotImplementedException('update function is not implemented! Override the function by subclassing Subscriber!')
@@ -36,6 +37,7 @@ class Publisher:
     def unregister(self, event, who):
         del self.get_subscribers(event)[who]
     
+        
     def dispatch(self, event, params=None):
         #print 'observer:: subscriber**** %s' % params
         for subscriber, callback in self.get_subscribers(event).items():
@@ -57,12 +59,12 @@ class Consumer(Subscriber):
     def __init__(self, name):
         Subscriber.__init__(self, name)
         
-    def update(self, event, param=None):
+    def update(self, event, **param):
         print('override %s: %s %s %s' % (self.name, event, "<empy param>" if not param else param,
                                          
                                          '<none>' if not param else param.__class__))
 
-    def trigger(self, event, param=None):
+    def trigger(self, event, **param):
         print('trigger %s: %s %s %s' % (self.name, event, "<empy param>" if not param else param,
                                          
                                          '<none>' if not param else param.__class__))

+ 0 - 0
src/sh (prod)/readme.1st~ → src/omrdapi/__init__.py


+ 243 - 0
src/omrdapi/v1/apiv1.py

@@ -0,0 +1,243 @@
+from flask_restful import Resource, Api, reqparse
+from misc2.helpers import ContractHelper, OrderHelper, OrderValidationException
+from time import sleep
+import uuid
+import traceback
+import json
+
+
+class Commands(Resource):
+    def get(self):
+        return {'status': True, 'Available REST API' : {'exit': 'shutdown gateway', 
+                                              'subscriptions': 'get a list of subscribed topics',
+                                              'settings': 'get gateway startup settings',
+                                               
+                                              }
+                }
+
+'''
+    function to force tws to return all open orders status
+    this function will only cause open orders status to be updated in the 
+    order manager
+    
+    this function is intend to test the TWS api function only.
+    clients that call this function would not be able to identify
+    what orders have their status returned from TWS. A higher level
+    function call (synchronized call) should be designed to retrieve the 
+    latest status from the order book instead
+    
+    
+'''
+class OpenOrdersStatus(Resource):
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        self.gw_conn = self.wc.get_parent().get_tws_connection()
+        
+    
+    def get(self):
+        try:
+            self.gw_conn.reqAllOpenOrders()
+            return {}, 201
+        except:
+
+            return {'error': 'no order details found !' }, 404
+
+'''
+    function to retrieve the status of an order given its order id
+    return 201 if record is found
+    else return 404
+'''
+class OrderStatus(Resource):
+    def __init__(self, webconsole): 
+        self.wc = webconsole
+        self.gw = self.wc.get_parent()
+    
+    def get(self, id):
+        om = self.gw.get_order_manager()
+        ob = om.get_order_book()
+        status =  ob.get_order_status(id)
+        if status:
+            return status, 201
+        else:
+            return {'error': 'no order details found for id [%s]' % id}, 404
+         
+        
+
+class OrderId(Resource):
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        self.gw = self.wc.get_parent()
+        
+
+    '''
+        function: checks whether the order id is in the order_id_manager given a clordid
+                  this is used for checking the result after creating a order using the 
+                  post method
+        arguments:
+            clordid should be unique across all clients (suggest to use uuid.uuid4) 
+        http://localhost:5001/order_id?client_id=1000&clordid=779
+    '''
+    def get(self):
+        parser = reqparse.RequestParser()
+        parser.add_argument('clordid', required=True, help="clordid is required.")    
+        args = parser.parse_args()
+        iom = self.gw.get_order_id_manager()
+        id = iom.assigned_id(args.get('clordid'))
+        if id == None:
+            return {}, 404
+        return id, 200
+        
+
+    ''' 
+        function: create a new order
+        arguments:
+            client_id is the application id
+            clordid should be unique across all clients (suggest to use uuid.uuid4) 
+        http://localhost:5001/order_id?client_id=1000&clordid=779
+    '''
+    def post(self):
+        parser = reqparse.RequestParser()
+        parser.add_argument('client_id', required=True, help="client_id is required.")
+        parser.add_argument('clordid', required=True, help="clordid is required.")    
+        args = parser.parse_args()
+        iom = self.gw.get_order_id_manager()
+        iom.request_id(args.get('client_id'), args.get('clordid'))
+        return {}, 201
+        
+
+class AsyncOrderCRUD(Resource):
+
+
+    def __init__(self, web_console):
+        self.wc = web_console
+        self.gw_conn = self.wc.get_parent().gw.get_tws_connection()
+
+    '''
+        
+        create order
+        arg: contract
+             order_condition
+    
+    '''    
+    def post(self, id):
+        parser = reqparse.RequestParser()
+        parser.add_argument('contract', required=True, help="contract is required.")
+        parser.add_argument('order_condition', required=True, help="order_condition is required.")
+        args = parser.parse_args()
+        js_contract = args.get('contract')
+        contract = ContractHelper.kvstring2contract(js_contract)
+        js_order_cond = args.get('order_condition')
+        order = OrderHelper.kvstring2object(js_order_cond)
+        self.gw_conn.placeOrder(int(id), contract, order)
+
+    
+    def get(self):
+        pass
+    
+    
+    def put(self):
+        pass
+    
+
+    def delete(self):
+        self.gw_conn.cancelOrder(int(id))
+   
+   
+        
+class SyncOrderCRUD(Resource):
+
+
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        self.gw_conn = self.wc.get_parent().get_tws_connection()
+        
+    '''
+        
+        create order
+        arg: contract
+             order_condition
+    
+    '''    
+    def post(self):
+        parser = reqparse.RequestParser()
+        parser.add_argument('contract', required=True, help="contract is required.")
+        parser.add_argument('order_condition', required=True, help="order_condition is required.")
+        args = parser.parse_args()
+        js_contract = args.get('contract')
+        contract = ContractHelper.kvstring2contract(js_contract)
+        js_order_cond = args.get('order_condition')
+        clordid = str(uuid.uuid4())
+        done = False
+        iom = self.wc.get_parent().get_order_id_manager()
+        iom.request_id('rest-api', clordid)
+        id = None
+        while not done:
+            id = iom.assigned_id(clordid)
+            if id != None:
+                break
+            sleep(0.5)
+        
+        try:    
+            order = OrderHelper.kvstring2object(js_order_cond)
+            OrderHelper.order_validation_ex(order)
+            self.gw_conn.placeOrder(id['next_valid_id'], contract, order)
+            return {'order id': id['next_valid_id']}, 201
+        
+        except OrderValidationException as e:
+            return {'error': e.args[0]}, 409
+        except ValueError:
+            return {'error': 'check the format of the order message! %s' % traceback.format_exc()}, 409
+    
+    def get(self):
+        pass
+    
+    
+    def put(self):
+        pass
+    
+
+    def delete(self):
+        try:
+            parser = reqparse.RequestParser()
+            parser.add_argument('id', required=True, help="order id is required")
+            args = parser.parse_args()
+            id = int(args['id'])
+            if self.wc.get_parent().get_order_manager().is_id_in_order_book(id):
+                self.gw_conn.cancelOrder(int(id))
+                return {'info': 'cancellation request sent. Check order status'}, 200
+            else:
+                return {'error': 'order id %d not found in order book' % id}, 404
+                
+        except:
+            return {'error': 'cancel order failed: %s ' % traceback.format_exc()}, 404
+            
+
+class ExitApp(Resource):
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        
+    def get(self):
+        self.wc.post_shutdown()
+        return {'status': 'please check the log for exit status'}
+        
+
+class GatewaySettings(Resource):
+    def __init__(self, gateway_instance):
+        self.gw = gateway_instance
+        
+    def get(self):
+        return json.loads(json.dumps(self.gw.kwargs))
+    
+    
+
+    
+
+
+class Subscriptions(Resource):
+    def __init__(self, gateway_instance):
+        self.gw = gateway_instance
+    
+    def get(self):
+        idc = self.gw.contract_subscription_mgr.get_id_contracts()
+        c2id = self.gw.contract_subscription_mgr.idContractMap['contract_id']
+        return {'status': True, 'subscriptions' : {'id2c': idc, 'c2id': c2id}}

+ 0 - 0
src/omrdapi/v2/__init__.py


+ 251 - 0
src/omrdapi/v2/apiv2.py

@@ -0,0 +1,251 @@
+from flask_restful import Resource, Api, reqparse
+from misc2.helpers import ContractHelper, OrderHelper, OrderValidationException
+from misc2.observer import Publisher
+from finopt.instrument import Symbol
+from time import sleep
+import uuid
+import traceback
+import json
+
+
+
+
+class InterestedTags():
+    
+    OrderStatus_tags = {'order': {'m_orderId': 'order_id'},
+                        'ord_status': {'status': 'status',
+                                       'filled': 'filled',
+                                       'remaining': 'remaining',
+                                       'avgFillPrice': 'avg_fill_price',
+                                       'permId': 'perm_id'},
+                        'error': {'errorCode': 'error_code',
+                                  'errorMsg': 'error_msg'}
+                        }
+    
+    
+    @staticmethod
+    def filter_unwanted_tags(o_status):
+        os = {}
+        for k,v in InterestedTags.OrderStatus_tags['order'].iteritems():
+            os[v] = o_status['order'][k]
+        for k,v in InterestedTags.OrderStatus_tags['ord_status'].iteritems():
+            os[v] = o_status['ord_status'][k]
+        try:
+            os['error'] = 'error_code:%d, error_msg:%s' % (o_status['errorCode'], o_status('errorMsg'))
+        except KeyError:
+            os['error'] = ''
+        
+        return os
+    
+'''
+    function to force tws to return all open orders status
+    this function will only cause open orders status to be updated in the 
+    order manager
+    
+    this function is intend to test the TWS api function only.
+    clients that call this function would not be able to identify
+    what orders have their status returned from TWS. A higher level
+    function call (synchronized call) should be designed to retrieve the 
+    latest status from the order book instead
+    
+    
+'''
+class OpenOrdersStatus_v2(Resource):
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        self.gw_conn = self.wc.get_parent().get_tws_connection()
+        
+    
+    def get(self):
+        try:
+            self.gw_conn.reqAllOpenOrders()
+            return {}, 201
+        except:
+
+            return {'error': 'no order details found!'}, 404
+
+'''
+    function to retrieve the status of an order given its order id
+    return 201 if record is found
+    else return 404
+'''
+class OrderStatus_v2(Resource):
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        self.gw = self.wc.get_parent()
+    
+    def get(self, id):
+        om = self.gw.get_order_manager() 
+        ob = om.get_order_book()
+        try:
+            status =  ob.get_order_status(id)
+            if status:
+                os = InterestedTags.filter_unwanted_tags(status)
+                return os, 201
+            else:
+                return {'error': 'no order details found for id [%s]' % id}, 404
+        except:
+            return {'error': 'error getting order status for [%s]' % id}, 404
+        
+
+   
+class v2_helper():
+    @staticmethod
+    def format_v2_str_to_contract(contract_v2str):
+    
+        mmap = {
+                "symbol": "m_symbol", 
+                "sec_type": "m_secType", 
+                "right": "m_right", 
+                "expiry": "m_expiry", 
+                "currency": "m_currency", 
+                "exchange": "m_exchange", 
+                "strike": 'm_strike'}
+        
+        cdict ={}
+        js_v2 = json.loads(contract_v2str)
+        for k,v in js_v2.iteritems():
+            if k in mmap:
+                 cdict[mmap[k]] = v
+        return ContractHelper.kv2contract(cdict)
+    
+
+    @staticmethod
+    def format_v2_str_to_order(order_v2str):
+        omap = {'order_type': 'm_orderType',
+                'account': 'm_account',
+                'side': 'm_action',
+                'quantity': 'm_totalQuantity', 
+                'price':'m_lmtPrice',
+                'aux_price': 'm_auxPrice'
+                }        
+    
+        
+        odict ={}
+        js_v2 = json.loads(order_v2str)
+        for k,v in js_v2.iteritems():
+            if k in omap:
+                 odict[omap[k]] = v
+        return OrderHelper.kv2object(odict)
+    
+
+        
+class SyncOrderCRUD_v2(Resource):
+
+
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        self.gw_conn = self.wc.get_parent().get_tws_connection()
+        
+        
+    
+    '''
+        
+        create order
+        arg: contract
+             order_condition
+    
+    '''    
+    def post(self):
+        parser = reqparse.RequestParser()
+        parser.add_argument('contract', required=True, help="contract is required.")
+        parser.add_argument('order_condition', required=True, help="order_condition is required.")
+        args = parser.parse_args()
+        js_contract = args.get('contract')
+        contract = v2_helper.format_v2_str_to_contract(js_contract)
+        js_order_cond = args.get('order_condition')
+        clordid = str(uuid.uuid4())
+        done = False
+        iom = self.wc.get_parent().get_order_id_manager()
+        iom.request_id('rest-api', clordid)
+        id = None
+        while not done:
+            id = iom.assigned_id(clordid)
+            if id != None:
+                break
+            sleep(0.5)
+        
+        try:    
+            order = v2_helper.format_v2_str_to_order(js_order_cond)
+            OrderHelper.order_validation_ex(order)
+            self.gw_conn.placeOrder(id['next_valid_id'], contract, order)
+            return {'order id': id['next_valid_id']}, 201
+        
+        except OrderValidationException as e:
+            return {'error': e.args[0]}, 409
+        except ValueError:
+            return {'error': 'check the format of the order message! %s' % traceback.format_exc()}, 409
+    
+    def get(self):
+        pass
+    
+    
+    def put(self):
+        pass
+    
+
+    def delete(self):
+        try:
+            parser = reqparse.RequestParser()
+            parser.add_argument('id', required=True, help="order id is required")
+            args = parser.parse_args()
+            id = int(args['id'])
+            if self.wc.get_parent().get_order_manager().is_id_in_order_book(id):
+                self.gw_conn.cancelOrder(int(id))
+                return {'info': 'cancellation request sent. Check order status'}, 200
+            else:
+                return {'error': 'order id %d not found in order book' % id}, 404
+        except:
+            return {'error': 'cancel order failed: %s ' % traceback.format_exc()}, 404
+            
+
+class QuoteRequest_v2(Resource, Publisher):
+    def __init__(self, webconsole):
+        self.wc = webconsole
+        self.contract_mgr = self.wc.get_parent().get_subscription_manager()
+        self.quote_mgr = self.wc.get_parent().get_quote_manager()
+        self.event = 'reqMktData'
+        Publisher.__init__(self, [self.event])
+        self.register(self.event, self.contract_mgr, callback=getattr(self.contract_mgr, self.event))
+    
+    def get(self):
+        parser = reqparse.RequestParser()
+        parser.add_argument('contract', required=True, help="contract is required.")
+        args = parser.parse_args()
+        contract = v2_helper.format_v2_str_to_contract(args['contract'])
+        
+        '''
+            if the contract is already in quote_handler
+                just read off the values from quote_handler and return
+            else
+                subscribe the contract by dispatching a request to subscription manager
+                loop
+                    check quote_handler for the contract
+                    if found, return values
+                    
+                
+        '''
+        def output_result(sym):
+            return {'asize': sym.get_tick_value(Symbol.ASKSIZE), 'ask': sym.get_tick_value(Symbol.ASK),
+                    'bsize': sym.get_tick_value(Symbol.BIDSIZE), 'ask': sym.get_tick_value(Symbol.BID),
+                    'last': sym.get_tick_value(Symbol.LAST), 'high': sym.get_tick_value(Symbol.LOW),
+                    'close': sym.get_tick_value(Symbol.CLOSE)}
+                        
+        sym = self.quote_mgr.get_symbol_ticks(contract)
+        if sym:
+            return output_result(sym), 200
+                    
+        else:
+            print ContractHelper.contract2kvstring(contract)
+            self.dispatch(self.event, {'contract': ContractHelper.contract2kvstring(contract), 'snapshot': False})
+            i = 0
+            while 1:
+                sym =  self.quote_mgr.get_symbol_ticks(contract)
+                if sym:
+                    break
+                sleep(0.5)
+                i += 0.5 
+                if i >= 10:
+                    return 'Not getting any quotes from the server after waited 5 seconds! Contact administrator', 404
+                
+            return output_result(sym), 200

+ 123 - 0
src/omrdapi/v2/quote_handler.py

@@ -0,0 +1,123 @@
+import logging
+import json
+from threading import RLock
+from misc2.observer import Subscriber
+from misc2.observer import NotImplementedException
+from misc2.helpers import ContractHelper
+
+import traceback
+from finopt.instrument import Symbol
+
+class QuoteRESTHandler(Subscriber):
+
+
+    '''
+    
+        self.symbols = {contract_key: Symbol, ...}
+        
+    '''
+    
+    def __init__(self, name, gw_parent):
+        
+        self.symbols = {}
+        self.name = name
+        self.gw_parent = gw_parent
+        self.tws_event_handler = gw_parent.get_tws_event_handler()
+        
+        Subscriber.__init__(self, self.name)
+        
+        '''
+             ask tws_event_handler to forward tick messages to
+             this class
+             
+        '''
+        for e in ['tickPrice', 'tickSize']:
+            self.tws_event_handler.register(e, self)           
+        
+
+    def handle_tickprice(self, contract_key, field, price, canAutoExecute):
+        logging.debug('QuoteHandler:tickPrice')
+        try:
+            s = self.symbols[contract_key]
+        except KeyError:
+            s = Symbol(ContractHelper.makeContractfromRedisKeyEx(contract_key))
+            self.symbols[contract_key] = s
+        s.set_tick_value(field, price)
+            
+            
+        
+    
+    def handle_ticksize(self, contract_key, field, size):
+        logging.debug('QuoteHandler:ticksize')
+        try:
+            s = self.symbols[contract_key]
+        except KeyError:
+            s = Symbol(ContractHelper.makeContractfromRedisKeyEx(contract_key))
+            self.symbols[contract_key] = s
+        s.set_tick_value(field, size)
+
+        
+    def update(self, event, **param): 
+        if event == 'tickPrice':
+            self.handle_tickprice(**param)
+        elif event == 'tickSize':
+            self.handle_ticksize(**param)
+        
+    
+    def get_symbol_ticks(self, contract):
+        try:
+            return self.symbols[ContractHelper.makeRedisKeyEx(contract)]
+        except KeyError:
+            return None
+        
+        
+    def dump(self):
+    
+        
+        def format_tick_val(val, fmt):
+            if val == None:
+                length = len(fmt % (0))
+                return ' ' * length
+            
+            return fmt % (val) 
+        
+        
+        fmt_spec = '%8.2f'
+        fmt_spec2 = '%8.4f'
+        fmt_specq = '%8d'
+        
+        
+        def get_field(sym, fld_id):
+            try:
+                return sym.get_tick_value(fld_id)
+            except:
+                return ''
+
+        
+        
+        fmt_sym = map(lambda x: (x[0], '%s,%s,%s,%s,%s,%s,%s' % (
+                                            format_tick_val(get_field(x[1],Symbol.LAST), fmt_spec),
+                                            format_tick_val(get_field(x[1],Symbol.BIDSIZE), fmt_specq),                                                                                                                  
+                                            format_tick_val(get_field(x[1],Symbol.BID), fmt_spec),
+                                            format_tick_val(get_field(x[1],Symbol.ASK), fmt_spec), 
+                                            format_tick_val(get_field(x[1],Symbol.ASKSIZE), fmt_specq),
+                                            format_tick_val(get_field(x[1],Symbol.CLOSE), fmt_spec),
+                                            format_tick_val(get_field(x[1],Symbol.VOLUME), fmt_specq),
+                                            )), [(k,v) for k, v in self.symbols.iteritems()])        
+        
+        print('%40s,%8s,%8s,%8s,%8s,%8s,%8s,%8s\n' % ('SYM', 'LAST', 'BIDSIZE','BID','ASK','ASKSIZE','CLOSE','VOLUME'
+                                             ))
+
+        for e in fmt_sym:
+            print('[%s]%s' % (e[0].ljust(40), e[1]))
+
+    
+    
+        
+
+
+
+
+        
+        
+        

+ 0 - 5
src/sh (prod)/alert.sh~

@@ -1,5 +0,0 @@
-#!/bin/bash
-ROOT=$FINOPT_HOME
-export PYTHONPATH=$FINOPT_HOME/src:$PYTHONPATH
-python $FINOPT_HOMEs/src/comms/alert_bot.py $FINOPT_HOME/config/app.cfg
-

+ 0 - 13
src/sh (prod)/md_std.sh

@@ -1,13 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-SRC=$ROOT/src
-KAFKA_ASSEMBLY_JAR=$ROOT/src/jar/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-export PYTHONPATH=$SRC:$PYTHONPATH
-OPTIONS="--driver-memory 2g"
-
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 simple 
-#spark-submit --total-executor-cores 2 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-spark-submit   --driver-memory 2g --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/md_std.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/t1.py
-

+ 0 - 13
src/sh (prod)/md_std2.sh

@@ -1,13 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-SRC=$ROOT/src
-KAFKA_ASSEMBLY_JAR=$ROOT/src/jar/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-export PYTHONPATH=$SRC:$PYTHONPATH
-OPTIONS="--driver-memory 2g"
-
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 simple 
-#spark-submit --total-executor-cores 2 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-spark-submit   $OPTIONS --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/md_std2.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/t1.py
-

+ 0 - 11
src/sh (prod)/momentum.sh

@@ -1,11 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-SRC=$ROOT/src
-KAFKA_ASSEMBLY_JAR=$ROOT/jar/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-export PYTHONPATH=$SRC:$PYTHONPATH
-
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 simple 
-#spark-submit --total-executor-cores 2 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-spark-submit  --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/momentum2.py vsu-01:2181 hsi 1 persist 
-

+ 0 - 11
src/sh (prod)/momentum.sh~

@@ -1,11 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-SRC=$ROOT/src
-KAFKA_ASSEMBLY_JAR=$ROOT/jar/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-export PYTHONPATH=$ROOT:$PYTHONPATH
-
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 simple 
-#spark-submit --total-executor-cores 2 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-spark-submit  --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/momentum2.py vsu-01:2181 hsi 1 persist 
-

+ 0 - 4
src/sh (prod)/momentum2.sh

@@ -1,4 +0,0 @@
-export PYTHONPATH=/home/larry-13.04/workspace/finopt:$PYTHONPATH
-KAFKA_ASSEMBLY_JAR=/home/larry-13.04/workspace/finopt/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-spark-submit --executor-cores 3 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/pairs_corr_redis.py vsu-01:2181 jpy  
-

+ 0 - 4
src/sh (prod)/pairs_corr_redis.sh

@@ -1,4 +0,0 @@
-export PYTHONPATH=/home/larry-13.04/workspace/finopt:$PYTHONPATH
-KAFKA_ASSEMBLY_JAR=/home/larry-13.04/workspace/finopt/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-spark-submit  --jars  /home/larry-13.04/workspace/finopt/spark-streaming-kafka-assembly_2.10-1.4.1.jar /home/larry-13.04/workspace/finopt/cep/pairs_corr_redis.py vsu-01:2181 hkd-aud 
-

+ 0 - 14
src/sh (prod)/port_stream.sh

@@ -1,14 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-SRC=$ROOT/src
-KAFKA_ASSEMBLY_JAR=$ROOT/src/jar/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-export PYTHONPATH=$SRC:$PYTHONPATH
-OPTIONS="--driver-memory 2g"
-
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 simple 
-#spark-submit --total-executor-cores 2 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit   $OPTIONS --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/port_stream.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/t1.py
-
-spark-submit   $OPTIONS --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/port_stream.py $SRC/config/cep.cfg vsu-01:2181 hsi 1 cal_trend 

+ 0 - 4
src/sh (prod)/portfolio.sh

@@ -1,4 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry/l1304/workspace/finopt/src
-export PYTHONPATH=$ROOT
-python $ROOT/finopt/portfolio.py $ROOT/config/app.cfg

+ 0 - 10
src/sh (prod)/readme.1st

@@ -1,10 +0,0 @@
-1. set up the environment variable
-	- open ~/.bashrc
-	- export FINOPT_HOME=/home/<user>/worker/finopt
-	- close the terminal and open again, check the
-	  environment variable is set correctly
-
-
-2. open each sh file, amend the path settings accordingly
-
-	

+ 0 - 8
src/sh (prod)/run_mds.sh

@@ -1,8 +0,0 @@
-#!/bin/bash
-ROOT=$FINOPT_HOME
-export PYTHONPATH=$FINOPT_HOME:$PYTHONPATH
-# real time mode
-python $FINOPT_HOME/cep/ib_mds.py $FINOPT_HOME/config/mds.cfg
-# replay mode
-#python $FINOPT_HOME/cep/ib_mds.py -r $FINOPT_HOME/../data/mds_files/20151006 $FINOPT_HOME/config/mds.cfg
-

+ 0 - 4
src/sh (prod)/run_mds.sh~

@@ -1,4 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-export PYTHONPATH=$ROOT/src
-python $ROOT/src/cep/ib_mds.py $ROOT/src/config/app.cfg

+ 0 - 4
src/sh (prod)/run_opt_serve.sh

@@ -1,4 +0,0 @@
-#!/bin/bash
-ROOT=~/l1304/production/finopt
-export PYTHONPATH=$ROOT
-python $ROOT/finopt/opt_serve.py $ROOT/config/app.cfg

+ 0 - 4
src/sh (prod)/run_opt_serve.sh~

@@ -1,4 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-export PYTHONPATH=$ROOT/src
-python $ROOT/src/finopt/opt_serve.py $ROOT/src/config/app.cfg

+ 0 - 5
src/sh (prod)/run_options_data.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-#ROOT={replace-path}
-ROOT=~/l1304/production/finopt
-export PYTHONPATH=$ROOT
-python $ROOT/finopt/options_data.py $ROOT/config/app.cfg

+ 0 - 4
src/sh (prod)/run_options_data.sh~

@@ -1,4 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-export PYTHONPATH=$ROOT/src
-python $ROOT/src/finopt/options_data.py $ROOT/src/config/app.cfg

+ 0 - 5
src/sh (prod)/start-alert.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-ROOT=$FINOPT_HOME
-export PYTHONPATH=$FINOPT_HOME:$PYTHONPATH
-python $FINOPT_HOME/comms/alert_bot.py $FINOPT_HOME/config/app.cfg
-

+ 0 - 4
src/sh (prod)/stop-alert.sh

@@ -1,4 +0,0 @@
-#!/bin/bash
-ps ax | grep -i 'alert' | grep python | grep -v grep | awk '{print $1}' | xargs kill -SIGTERM
-
-

+ 0 - 13
src/sh (prod)/t1.sh

@@ -1,13 +0,0 @@
-#!/bin/bash
-
-ROOT=$FINOPT_HOME
-FINDATA=$ROOT/../data 
-SRC=$ROOT
-KAFKA_ASSEMBLY_JAR=$ROOT/jar/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-export PYTHONPATH=$SRC:$PYTHONPATH
-
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 simple 
-#spark-submit --total-executor-cores 2 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-spark-submit  --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/t1.py $FINDATA/mds_files/large_up_1002
-

+ 0 - 11
src/sh (prod)/t1.sh~

@@ -1,11 +0,0 @@
-#!/bin/bash
-ROOT=/home/larry-13.04/workspace/finopt
-SRC=$ROOT/src
-KAFKA_ASSEMBLY_JAR=$ROOT/src/jar/spark-streaming-kafka-assembly_2.10-1.4.1.jar
-export PYTHONPATH=$SRC:$PYTHONPATH
-
-#spark-submit  --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-#spark-submit --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 simple 
-#spark-submit --total-executor-cores 2 --master spark://192.168.1.118:7077   --jars  $KAFKA_ASSEMBLY_JAR /home/larry-13.04/workspace/finopt/cep/momentum.py vsu-01:2181 hsi 1 cal_trend 
-spark-submit  --jars  $KAFKA_ASSEMBLY_JAR $SRC/cep/t1.py
-

+ 6 - 1
src/sh/pm.sh

@@ -7,7 +7,12 @@ echo $HOST
 if [ $HOST == 'hkc-larryc-vm1' ]; then
 	FINOPT_HOME=~/ironfly-workspace/finopt/src
 elif [ $HOST == 'astron' ]; then
-	FINOPT_HOME=~/workspace/finopt/src
+	#FINOPT_HOME=~/workspace/finopt/src
+
+	# virtual env
+	FINOPT_HOME=~/workspace/fpydevs/eclipse/finopt/src
+	source /home/laxaurus/workspace/fpydevs/env/bin/activate
+
 elif [ $HOST == 'vsu-longhorn' ]; then
     FINOPT_HOME=~/pyenvs/ironfly/finopt/src
     source /home/vuser-longhorn/pyenvs/finopt/bin/activate

+ 7 - 1
src/sh/start_twsgw.sh

@@ -8,7 +8,13 @@ if [ $HOST == 'hkc-larryc-vm1' ]; then
 elif [ $HOST == 'vorsprung' ]; then
 	FINOPT_HOME=~/workspace/finopt/src
 elif [ $HOST == 'astron' ]; then
-	FINOPT_HOME=~/workspace/finopt/src
+	#	FINOPT_HOME=~/workspace/finopt/src
+
+	# virtual env
+	FINOPT_HOME=~/workspace/fpydevs/eclipse/finopt/src
+	source /home/laxaurus/workspace/fpydevs/env/bin/activate
+
+
 elif [ $HOST == 'vsu-longhorn' ]; then
         FINOPT_HOME=~/pyenvs/ironfly/finopt/src
         source /home/vuser-longhorn/pyenvs/finopt/bin/activate