Quellcode durchsuchen

changed options calculation

larry vor 10 Jahren
Ursprung
Commit
271897c009

+ 18 - 8
cep/port_stream.py

@@ -13,7 +13,7 @@ import os
 #from finopt import ystockquote
 from comms.epc import ExternalProcessComm
 import ConfigParser
- 
+import logging 
 ##
 ##
 ##
@@ -111,7 +111,14 @@ if __name__ == "__main__":
         exit(-1)    
 
     cfg_path= sys.argv[1:]    
-    config = ConfigParser.ConfigParser()
+    config = ConfigParser.SafeConfigParser()
+    if len(config.read(cfg_path)) == 0:      
+        raise ValueError, "Failed to open config file" 
+    
+    logconfig = eval(config.get("cep", "cep.logconfig").strip('"').strip("'"))
+    logconfig['format'] = '%(asctime)s %(levelname)-8s %(message)s'    
+    logging.basicConfig(**logconfig)        
+                                       
 
     param = {}
     param['broker'] = 'vsu-1:2181'
@@ -162,18 +169,21 @@ if __name__ == "__main__":
                 .window(param['win_interval'],param['slide_interval'])
     pl_st = jport_st.filter(lambda x: x[1] == 'port_item')\
                 .window(param['win_interval'],param['slide_interval'])
-    
+    acct_st = jport_st.filter(lambda x: x[1] == 'acct_summary')\
+                .window(param['win_interval'],param['slide_interval'])
     
     # listen to ib_mds price updates
-    ib_st = KafkaUtils.createStream(ssc, brokers, param['app_name'], {'ib_tick_price':1, 'ib_tick_size':1})\
-                         .filter(lambda x: (x['typeName'] == 'tickPrice'))\
-                         .map(lambda x: (x['contract'], (x['ts'], x['price']) ))\
-                         .groupByKeyAndWindow(param['win_interval'],param['slide_interval'], 1)
+#     ib_st = KafkaUtils.createStream(ssc, brokers, param['app_name'], {'ib_tick_price':1, 'ib_tick_size':1})\
+#                          .filter(lambda x: (x['typeName'] == 'tickPrice'))\
+#                          .map(lambda x: (x['contract'], (x['ts'], x['price']) ))\
+#                          .groupByKeyAndWindow(param['win_interval'],param['slide_interval'], 1)
+    
+    
     
     
     #lns.pprint()
  
-    pt_st.foreachRDD(f2)
+    acct_st.foreachRDD(f2)
 # 
 #     sps.pprint()
     #trades.foreachRDD(eval(fn))

+ 10 - 4
comms/epc.py

@@ -19,8 +19,7 @@ class EPCPub():
     
     producer = None
 
-    EPC_TOPICS= {'EPC_PORT_SUMMARY_TOPIC': 'port_summary', 
-                 'EPC_PORT_ITEM_TOPIC': 'port_item'}
+
     
     def __init__(self, config):
 
@@ -48,7 +47,9 @@ class EPCPub():
         self.post_msg(ExternalProcessComm.EPC_TOPICS['EPC_PORT_ITEM_TOPIC'], json.dumps(msg))
                              
 
-
+    def post_account_summary(self, dict):
+        msg = (time.time(), ExternalProcessComm.EPC_TOPICS['EPC_ACCT_SUMMARY_TOPIC'], dict)
+        self.post_msg(ExternalProcessComm.EPC_TOPICS['EPC_ACCT_SUMMARY_TOPIC'], json.dumps(msg))
 
         
 class ExternalProcessComm(threading.Thread):
@@ -56,7 +57,8 @@ class ExternalProcessComm(threading.Thread):
     producer = None
     consumer = None
     EPC_TOPICS= {'EPC_PORT_SUMMARY_TOPIC': 'port_summary', 
-                 'EPC_PORT_ITEM_TOPIC': 'port_item'}
+                 'EPC_PORT_ITEM_TOPIC': 'port_item',
+                 'EPC_ACCT_SUMMARY_TOPIC': 'acct_summary'}
     
     def __init__(self, config):
 
@@ -104,6 +106,10 @@ class ExternalProcessComm(threading.Thread):
     def post_portfolio_items(self, ldict):
         msg= (time.time(), ldict)
         self.post_msg(ExternalProcessComm.EPC_TOPICS['EPC_PORT_ITEM_TOPIC'], json.dumps(msg))
+        
+    def post_account_summary(self, dict):
+        msg = (time.time(), dict)
+        self.post_msg(ExternalProcessComm.EPC_TOPICS['EPC_ACCT_SUMMARY_TOPIC'], json.dumps(msg))
                              
     def run(self):
         

BIN
comms/epc.pyc


+ 3 - 1
config/app.cfg

@@ -20,6 +20,7 @@ redis.datastore.key.port_prefix: 'PT'
 # to retrive its value just use rs.get instead of self.rs_<xxx>
 redis.datastore.key.port_summary: 'port_summary'
 redis.datastore.key.port_items: 'port_items'
+redis.datastore.key.acct_summary: 'acct_summary'
  
 [/]
 tools.sessions.on : True
@@ -42,7 +43,8 @@ options_data.logconfig: "{'filename': '/home/larry-13.04/workspace/finopt/log/op
 [portfolio]
 portfolio.logconfig: "{'filename': '/home/larry-13.04/workspace/finopt/log/port.log', 'filemode': 'w','level': logging.INFO}"
 portfolio.epc: "{'stream_to_Kafka': True}"   
-#, 'msg_port_summary':{'topic': 'port_summary'}, 'msg_port_line':{'topic': 'port_line'}}"
+portfolio.account_summary_tags: "['AccountType','NetLiquidation','TotalCashValue','SettledCash','AccruedCash','BuyingPower','EquityWithLoanValue','PreviousDayEquityWithLoanValue','GrossPositionValue','RegTEquity','RegTMargin','SMA','InitMarginReq','MaintMarginReq','AvailableFunds','ExcessLiquidity','Cushion','FullInitMarginReq','FullMaintMarginReq','FullAvailableFunds','FullExcessLiquidity','LookAheadNextChange','LookAheadInitMarginReq','LookAheadMaintMarginReq','LookAheadAvailableFunds','LookAheadExcessLiquidity','HighestSeverity','DayTradesRemaining','Leverage']"
+
 
 [opt_serve]
 opt_serve.logconfig: "{'filename': '/home/larry-13.04/workspace/finopt/log/serve.log', 'filemode': 'w','level': logging.INFO}"

+ 84 - 0
config/cep.cfg

@@ -0,0 +1,84 @@
+[redis]
+redis.server: "localhost"
+redis.port: 6379
+redis.db: 3
+redis.sleep: 0.5
+redis.datastore.key.option_implv: 'opt_implv'
+redis.datastore.key.option_chains: 'opt_chains'
+redis.datastore.key.option_set: 'opt_set'
+redis.datastore.key.option_implv_ts_set: 'opt_implv_ts_set'
+redis.datastore.key.option_implv_ts: 'opt_implv_ts' 
+
+# a redis key that stores all the contract ids of contracts in a portfolio  
+redis.datastore.key.port_conid_set: 'port_conid_set' 
+redis.datastore.key.port_prefix: 'PT'
+# note that the port summary key has no prefix assigned to it
+# to retrive its value just use rs.get instead of self.rs_<xxx>
+redis.datastore.key.port_summary: 'port_summary'
+redis.datastore.key.port_items: 'port_items'
+redis.datastore.key.acct_summary: 'acct_summary'
+ 
+
+
+[cep]
+kafka.host: 'vsu-01'
+kafka.port: 9092
+kafka.ib.topic.tick_price: 'ib_tick_price'
+kafka.ib.topic.tick_size: 'ib_tick_size'
+ib.subscription.fileloc: '/home/larry-13.04/workspace/finopt/data/subscription.txt'
+cep.logconfig: "{'filename': '/home/larry-13.04/workspace/finopt/log/cep_{{{appname}}}.log', 'filemode': 'w','level': logging.INFO}"
+
+[market]
+hkex.openhours: '{"morning":[915,1200], "afternoon":[1300,1615]}'
+#ib.gateway: '127.0.0.1'
+ib.gateway: 'vsu-01'
+ib.port: 7496
+#gw port
+#ib.port:4001
+ib.appid.portfolio: 9922
+
+ib.appid: 9911
+option.underlying = "('HSI', 'FUT', 'HKFE', 'HKD', '', 0, '')"
+option.underlying.month_price = "[['20151029', 22817.0, '^HSI'], ['20151127', 22715.0, '^HSI']]"
+option.underlying.yahoo_ws = "{'use_yahoo': True, 'func': 'ystockquote.get_price'}"
+option.underlying.tick_size = 200
+option.greeks.recal = "{'use_last_if_no_bidask': True, 'rate':0.005, 'div':0.005, 'vol':0.2}"
+option.chain_range = 0.08
+option.bid_ask_spread_tolerance = 0.90
+
+[alert_bot]
+msg_bot.jid: "robo@route69.hopto.org"
+msg_bot.pass: 123
+msg_bot.recipients: "['blueman@route69.hopto.org']"
+msg_bot.redis_mq: 'chatq'
+msg_bot.redis_prefix: 'alert_bot'  
+#
+# 'filename': '../log/alert_bot.log', 'filemode': 'w', 
+msg_bot.logconfig: "{'level': logging.INFO}"
+
+[epc]
+kafka.host: 'vsu-01'
+kafka.port: 9092
+
+[ib_mds]
+ib_mds.logconfig: "{'filename': '/home/larry-13.04/workspace/finopt/log/ib_mds.log', 'filemode': 'w','level': logging.INFO}"
+ib_mds.ib_port: 7496
+#ib_mds.ib_port: 4001
+ib_mds.appid.id: 9800
+ib_mds.gateway: 'localhost'
+#ib_mds.gateway: '192.168.1.118'
+ib_mds.is_persist: 1
+ib_mds.persist_dir: '/home/larry-13.04/workspace/finopt/data/mds_files'
+ib_mds.spill_over_limit: 10000
+
+[ib_heartbeat]
+ib_heartbeat.logconfig: "{'filename': '/home/larry-13.04/workspace/finopt/log/ib_mds.log', 'filemode': 'w','level': logging.INFO}"
+#ib_heartbeat.ib_port: 4001
+ib_heartbeat.ib_port: 7496
+ib_heartbeat.appid.id: 9911
+ib_heartbeat.gateway: 'localhost'
+#ib_heartbeat.gateway: '192.168.1.118'
+ib_heartbeat.try_interval: 3
+ib_heartbeat.suppress_msg_interval: 60
+
+

+ 6 - 2
finopt/misc/misc_utils.py

@@ -22,7 +22,10 @@ from kafka.producer import SimpleProducer
 from comms.alert_bot import AlertHelper
 
 
-
+def get_ib_acct_tags(file):
+    f = open(file)
+    ln = f.readlines()
+    return ''.join("'%s'," % s.replace('\n', '').strip(' ') for s in ln)
 
 
 
@@ -61,5 +64,6 @@ def create_subscription_file(src, dest):
 #         newContract.m_right = contractTuple[6]
 
 if __name__ == '__main__':
-    create_subscription_file('/home/larry-13.04/workspace/finopt/log/hsio.txt', '/home/larry-13.04/workspace/finopt/log/subo.txt')
+    #create_subscription_file('/home/larry-13.04/workspace/finopt/log/hsio.txt', '/home/larry-13.04/workspace/finopt/log/subo.txt')
+    print get_ib_acct_tags('/home/larry/l1304/workspace/finopt/data/temp_data/ib_account_summary_tags')
     

+ 49 - 13
finopt/opt_serve.py

@@ -394,6 +394,30 @@ class QServer(object):
     @cherrypy.expose
     def port_bubble_chart(self):
     
+        s_data = self.ws_bubble_data()
+
+        bubble_chart_tmpl = '%s%s/bubble-port.html' % (cherrypy.request.app.config['/']['tools.staticdir.root'], cherrypy.request.app.config['/static']['tools.staticdir.tmpl'])
+        f = open(bubble_chart_tmpl)
+        html_tmpl = f.read()
+        html_tmpl = html_tmpl.replace('{{{bubble_data}}}', s_data)
+        
+        contract_month = eval(cherrypy.request.app.config['market']['option.underlying.month_price'])[0][0]
+        html_tmpl = html_tmpl.replace('{{{FUT_CONTRACT}}}', 'HSI-%s-FUT-' % (contract_month))
+        
+        
+        
+        s_acctitems, last_updated, account_no = self.ws_acct_data()
+        print s_acctitems, last_updated, account_no
+        html_tmpl = html_tmpl.replace('{{{barAcct}}}', s_acctitems)
+        html_tmpl = html_tmpl.replace('{{{account_no}}}', account_no)
+        html_tmpl = html_tmpl.replace('{{{last_updated}}}', last_updated)
+        
+        
+        
+        return html_tmpl
+       
+    @cherrypy.expose
+    def ws_bubble_data(self):
         # Tick Value      Description
         # 5001            impl vol
         # 5002            delta
@@ -414,9 +438,12 @@ class QServer(object):
         # 6021            pos value impact -1% vol change
         s_portitems = self.ws_port_items() 
         
-        ldict = json.loads(s_portitems)
-        lcontract = map(lambda x: x['contract'], ldict)
+        litems = json.loads(s_portitems)
         
+        # only interested in unrealized items, pos != 0 
+        ldict = filter(lambda x: x['6002'] <> 0, litems)
+        
+        lcontract = map(lambda x: x['contract'], ldict)
         lpos_delta = map(lambda x: x['6005'], ldict)
         lstrike = map(lambda x: x['contract'].split('-')[2], ldict)
         ltheta = map(lambda x:  x['6006'], ldict)
@@ -428,17 +455,26 @@ class QServer(object):
         colnames = "[['contract', 'strike', 'unreal PL', 'theta', 'delta'],"
         print '----------------------'
         s_data = colnames + ''.join('["%s",%s,%s,%s,%s],' % (lcontract[i], lstrike[i], lupl[i], ltheta[i], lpos_delta[i]) for i in range(len(lcontract)))+ ']'
-
-
-        bubble_chart_tmpl = '%s%s/bubble-port.html' % (cherrypy.request.app.config['/']['tools.staticdir.root'], cherrypy.request.app.config['/static']['tools.staticdir.tmpl'])
-        f = open(bubble_chart_tmpl)
-        html_tmpl = f.read()
-        html_tmpl = html_tmpl.replace('{{{bubble_data}}}', s_data)
-        
-        contract_month = eval(cherrypy.request.app.config['market']['option.underlying.month_price'])[0][0]
-        html_tmpl = html_tmpl.replace('{{{FUT_CONTRACT}}}', 'HSI-%s-FUT-' % (contract_month))
-        return html_tmpl
-        
+      
+        return s_data
+    
+    
+            
+    
+    
+    @cherrypy.expose
+    def ws_acct_data(self):
+        rs = QServer.r_conn
+        key = cherrypy.request.app.config['redis']['redis.datastore.key.acct_summary']
+        s_acctitems = rs.get(key)
+        dict = json.loads(s_acctitems)
+        colnames = "[['Category', 'Value', { role: 'style' } ],"
+        unwanted_cols = ['DayTradesRemaining','last_updated', 'AccountType']
+        s_data = colnames + ''.join('["%s", %s, "%s"],' % (k, '%s'%(v[0]), '#3366CC' if float(v[0]) > 500000 else '#DC3912') if k not in unwanted_cols else '' for k, v in dict.iteritems()   )+ ']'
+      
+        return (s_data, dict['last_updated'], dict['AccountType'][2])
+    
+    
     
     @cherrypy.expose
     def ws_msg_bot(self, msg):

BIN
finopt/opt_serve.pyc


+ 56 - 11
finopt/optcal.py

@@ -11,11 +11,13 @@ def cal_implvol(spot, strike, callput, evaldate, exdate, rate, div, vol, premium
     payoff = PlainVanillaPayoff(str2qopt_type(callput), strike)
     option = EuropeanOption(payoff,exercise)
     S = QuoteHandle(SimpleQuote(spot))
-    r = YieldTermStructureHandle(FlatForward(0, TARGET(), rate, Actual360()))
-    q = YieldTermStructureHandle(FlatForward(0, TARGET(), div, Actual360()))
-    sigma = BlackVolTermStructureHandle(BlackConstantVol(0, TARGET(), vol, Actual360()))
+#     r = YieldTermStructureHandle(FlatForward(0, HongKong(), rate, Actual365Fixed()))
+#     q = YieldTermStructureHandle(FlatForward(0, HongKong(), div, Actual365Fixed()))
+    r = YieldTermStructureHandle(FlatForward(str2qdate(evaldate), rate, Actual365Fixed()))
+    q = YieldTermStructureHandle(FlatForward(str2qdate(evaldate), div, Actual365Fixed()))
+
+    sigma = BlackVolTermStructureHandle(BlackConstantVol(str2qdate(evaldate), HongKong(), vol, Actual365Fixed()))
     process = BlackScholesMertonProcess(S,q,r,sigma)
-    im = 0.0
     im = option.impliedVolatility(premium, process)
     results = {}
     results['imvol'] = im
@@ -31,9 +33,13 @@ def cal_option(spot, strike, callput, evaldate, exdate, rate, div, vol):
     payoff = PlainVanillaPayoff(str2qopt_type(callput), strike)
     option = EuropeanOption(payoff,exercise)
     S = QuoteHandle(SimpleQuote(spot))
-    r = YieldTermStructureHandle(FlatForward(0, TARGET(), rate, Actual360()))
-    q = YieldTermStructureHandle(FlatForward(0, TARGET(), div, Actual360()))
-    sigma = BlackVolTermStructureHandle(BlackConstantVol(0, TARGET(), vol, Actual360()))
+#    r = YieldTermStructureHandle(FlatForward(0, HongKong(), rate, Actual365Fixed()))
+#    q = YieldTermStructureHandle(FlatForward(0, HongKong(), div, Actual365Fixed()))
+    r = YieldTermStructureHandle(FlatForward(str2qdate(evaldate), rate, Actual365Fixed()))
+    q = YieldTermStructureHandle(FlatForward(str2qdate(evaldate), div, Actual365Fixed()))
+
+#    sigma = BlackVolTermStructureHandle(BlackConstantVol(0, HongKong(), vol, Actual365Fixed()))
+    sigma = BlackVolTermStructureHandle(BlackConstantVol(str2qdate(evaldate), HongKong(), vol, Actual365Fixed()))
     process = BlackScholesMertonProcess(S,q,r,sigma)
     engine = AnalyticEuropeanEngine(process)
     option.setPricingEngine(engine)
@@ -44,8 +50,8 @@ def cal_option(spot, strike, callput, evaldate, exdate, rate, div, vol):
     results['delta'] = option.delta()
     results['gamma'] = option.gamma()
     
-    results['theta'] = option.theta() / 360
-    results['vega'] = option.vega()    
+    results['theta'] = option.theta() / 365
+    results['vega'] = option.vega() 
 
  
 
@@ -67,6 +73,10 @@ def str2qopt_type(callput):
     return Option.Put
 
 if __name__ == '__main__':
+    
+    
+#http://stackoverflow.com/questions/4891490/calculating-europeanoptionimpliedvolatility-in-quantlib-python
+    
     # todaysDate = Date(10,August, 2015)
     # Settings.instance().evaluationDate = todaysDate
     # 
@@ -101,10 +111,45 @@ if __name__ == '__main__':
     #spot 24119.0, X 25000, right: P, evaldate: 20150812, expiry: 20150828, rate: 0.0005, div: 0.0005, vol: 0.2000, premium: 334.0000
     #spot 24149.0, X 25200, right: P, evaldate: 20150812, expiry: 20150828, rate: 0.0005, div: 0.0005, vol: 0.2000, premium: 437.5000
     
-    results = cal_option(24149.0, 25200, 'P', '20150812', '20150828', 0.0005, 0.0005, 0.19)
+    results = cal_option(23067.0, 22000, 'P', '20151018', '20151030', 0.0009, 0.0328, 0.2918)
+    print ''.join ('%s=%0.4f, '%(k,v) for k, v in results.iteritems())
+    results = cal_option(23067.0, 22000, 'P', '20151018', '20151029', 0.0009, 0.0328, 0.2918)
+    npv1 = results['npv']
+    v1 = 0.2918
+
+    
+    print ''.join ('%s=%0.4f, '%(k,v) for k, v in results.iteritems())
+    results = cal_option(23067.0, 22000, 'C', '20151018', '20151029', 0.0009, 0.0328, 0.2918)
+    print ''.join ('%s=%0.4f, '%(k,v) for k, v in results.iteritems())
+
+    results = cal_option(23067.0, 22000, 'P', '20151018', '20151029', 0.0009, 0.0328, 0.2918*1.01)
+    print ''.join ('%s=%0.4f, '%(k,v) for k, v in results.iteritems())
+    npv2 = results['npv']
+    v2 = v1 * 1.01
+    
+    print 'validating vega: (%0.2f - %0.2f) / (%0.4f - %0.4f) = %0.2f' % (npv2, npv1, v2, v1, (npv2-npv1)/ (v2 - v1))     
+    
+    
+    results = cal_option(23067.0, 22000, 'C', '20151018', '20151029', 0.0009, 0.0328, 0.2918*1.01)
     print ''.join ('%s=%0.4f, '%(k,v) for k, v in results.iteritems())
-    results = cal_implvol(24149.0, 25200, 'P', '20150812', '20150828', 0.0005, 0.0005, 0.19, 1247)
+
+    
+ 
+    
+    results = cal_implvol(23067.0, 21000, 'P', '20151018', '20151030', 0.0009, 0.0328, 0.19, 14.5817)
     
         
     print ''.join ('%s=%0.4f, '%(k,v) for k, v in results.iteritems())
 
+
+    chk = HongKong()
+    chk.addHoliday(Date(24, December, 2015))
+    chk.addHoliday(Date(19, October, 2015))
+    chk.addHoliday(str2qdate('20151020'))
+    print chk.isBusinessDay(Date(24, December, 2015))
+    print chk.isBusinessDay(Date(19, October, 2015))
+    print chk.isEndOfMonth(Date(29, October, 2015))
+    print chk.isEndOfMonth(Date(30, October, 2015))
+    print chk.advance(Date(17, October, 2015), 1, 0)
+    print chk.advance(Date(17, October, 2015), 1, 1)
+    print chk.advance(Date(17, October, 2015), 1, 2)

BIN
finopt/optcal.pyc


+ 42 - 9
finopt/portfolio.py

@@ -50,18 +50,21 @@ class PortfolioManager():
     r_conn = None
     port = []
     grouped_options = None
-    download_state = 'undone'
+    
+    # item 0 is for position, item 1 is for account
+    download_states = [False, False]
     quit = False
     interested_types = ['OPT', 'FUT']
     rs_port_keys = {}
     ib_port_msg = []
     tlock = None
     epc = None
+    account_tags = []
+    ib_acct_msg = {}
     
     def __init__(self, config):
         self.config = config
-#        config = ConfigParser.ConfigParser()
-#        config.read("config/app.cfg")
+
         host = config.get("market", "ib.gateway").strip('"').strip("'")
         port = int(config.get("market", "ib.port"))
         appid = int(config.get("market", "ib.appid.portfolio"))   
@@ -70,6 +73,10 @@ class PortfolioManager():
         self.rs_port_keys['port_summary'] = config.get("redis", "redis.datastore.key.port_summary").strip('"').strip("'")
         self.rs_port_keys['port_items'] = config.get("redis", "redis.datastore.key.port_items").strip('"').strip("'")
         
+        
+        self.rs_port_keys['acct_summary'] = config.get("redis", "redis.datastore.key.acct_summary").strip('"').strip("'") 
+        self.account_tags = eval(config.get("portfolio", "portfolio.account_summary_tags").strip('"').strip("'"))
+        
         self.epc = eval(config.get("portfolio", "portfolio.epc").strip('"').strip("'"))
         # instantiate a epc object if the config says so
         
@@ -99,7 +106,8 @@ class PortfolioManager():
         
         self.subscribe()
         while not self.quit:
-            if self.download_state == 'done':
+            if self.download_states[0] == True and self.download_states[1] == True:
+                self.disconnect()
                 self.quit = True
                 
     def clear_redis_portfolio(self):
@@ -113,16 +121,17 @@ class PortfolioManager():
     def subscribe(self):
 
             self.con.reqPositions()
-            #self.con.reqAccountSummary(100,'All', 'EquityWithLoanValue,NetLiquidation')
+            logging.debug('account info to retrieve: %s' % (''.join('%s,' % s for s in self.account_tags)))
+            self.con.reqAccountSummary(100, 'All', ''.join('%s,' % s for s in self.account_tags))
 
             #self.con.register(self.on_ib_message, 'UpdateAccountValue')
 
     def on_ib_message(self, msg):
         
-        
+        #print msg.typeName, msg
         
         if msg.typeName in "position":
-            if self.download_state == 'undone':
+            if self.download_states[0] == False:
                 logging.debug("%s" %  (options_data.ContractHelper.printContract(msg.contract)))
                 if msg.contract.m_secType in self.interested_types:
                     logging.debug("PortfolioManager: getting position...%s" % msg)
@@ -138,11 +147,35 @@ class PortfolioManager():
             self.recal_port()
             self.group_pos_by_strike()
             logging.debug("PortfolioManager: Complete position download. Disconnecting...")
-            self.disconnect()
             
 
+            self.download_states[0] = True
+            
+        if msg.typeName == "accountSummary":
+            if self.download_states[1] == False:
+                
+                self.ib_acct_msg[msg.tag] = (msg.value, msg.currency, msg.account)
+                logging.debug("PortfolioManager: getting account info...%s" % msg)
+            
+        if msg.typeName == 'accountSummaryEnd':
+            
+            self.ib_acct_msg['last_updated'] = datetime.datetime.now().strftime('%Y%m%d%H%M%S') 
+            logging.info("-------------- ACCOUNT SUMMARY [%s]" % (self.ib_acct_msg['AccountType'][2]))
+            logging.info('\n\n' + ''.join('%30s: %22s\n' % (k, ''.join('%10s %12s' % (v[0], v[1] if v[1] else ''))) for k,v in self.ib_acct_msg.iteritems()))
+            
+            self.r_conn.set(self.rs_port_keys['acct_summary'], json.dumps(self.ib_acct_msg))
+            if self.epc['epc']:
+                try:
 
-            self.download_state = "done"
+                    self.epc['epc'].post_account_summary(self.ib_acct_msg)
+
+                except:
+                    logging.exception("Exception in function when trying to broadcast account summary message to epc")
+            
+            self.download_states[1] = True
+        
+            
+            
             
     def group_pos_by_strike(self):
 

BIN
finopt/portfolio.pyc


+ 213 - 0
html/bubble-port-no-tabs.html

@@ -0,0 +1,213 @@
+<html>
+  <head>
+   <style>
+   .chartWithMarkerOverlay {
+       position: relative;
+       width: 700px;
+   }
+   .overlay-text {
+       width: 200px;
+       height: 200px;
+       position: absolute;
+       top: 30px;   /* chartArea top */
+       left: 200px; /* chartArea left */
+   }
+   .overlay-marker {
+       width: 50px;
+       height: 50px;
+       position: absolute;
+       top: 375px;   /* chartArea top */
+       left: 350px; /* chartArea left */
+       color: #000066;
+       font: 15px arial;
+    
+   }
+   </style>
+  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
+    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+    <script type="text/javascript">
+      google.load("visualization", "1.1", {packages:['corechart']});
+      google.setOnLoadCallback(drawChart);
+      function drawChart() {
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// guage functions
+
+
+		var data = google.visualization.arrayToDataTable( 
+{{{bubble_data}}}
+		); 
+
+
+		var options = { title: 'Portfolio Risk Distribution', 
+			hAxis: {title: 'Strike Price'}, vAxis: {title: ' Unreal P/L'}, 
+			// to display labels, remove the color: 'none option
+			bubble: {textStyle: {fontSize: 11, color: 'none'}}, colorAxis: {colors: ['red', 'blue']},
+			sizeAxis: {minValue: 2,  maxSize: 40}
+			//backgroundColor: '#E4E4E4'
+		 }; 
+
+
+		var chart = new google.visualization.BubbleChart(document.getElementById('chart_div')); 
+		chart.draw(data, options); 
+
+
+		google.visualization.events.addListener(chart, 'ready', placeIndexMarker);
+		
+		var button = document.getElementById('b1');
+
+		button.onclick = function() {
+			refreshPortItems();
+			refreshAcctItems();
+
+		}
+
+		setInterval(function() {
+		  placeIndexMarker();
+		}, 2000);
+
+
+
+		function refreshPortItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_bubble_data',
+			success: function (s_portitems) {
+
+
+				$('#pt_status').text(s_portitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				data = google.visualization.arrayToDataTable(eval(s_portitems));
+				chart.draw(data, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+
+		function refreshAcctItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_acct_data',
+			success: function (s_accttitems) {
+
+
+				$('#pt_status').text(s_accttitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				dataB = google.visualization.arrayToDataTable(eval(s_accttitems));
+				chart.draw(dataB, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+		function placeIndexMarker(){
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_market_data?r_ckey={{{FUT_CONTRACT}}}&fid=4',
+			success: function (data) {
+
+				var spot = data
+				$('#spot').text(spot);
+
+				var cli = chart.getChartLayoutInterface();
+				document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+				document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot) - 25) + "px";
+
+			}
+		    });
+
+
+		var dataB = google.visualization.arrayToDataTable(
+{{{barAcct}}}
+		);
+
+		var view = new google.visualization.DataView(dataB);
+		view.setColumns([0, 1,
+			       { calc: "stringify",
+				 sourceColumn: 1,
+				 type: "string",
+				 role: "annotation" }, 2]);
+
+		var options = {
+		chart: {
+		  title: 'Account Summary {{{account_no}}}',
+		  subtitle: 'Last updated {{{last_updated}}}'
+		},
+
+		bars: 'horizontal',bar: {groupWidth: "55%"},
+
+		  legend: { position: "none" },
+		};
+		var material = new google.visualization.BarChart(document.getElementById('barchart_div'));
+		material.draw(view, options);
+
+		}
+
+
+
+//https://groups.google.com/forum/#!msg/google-chart-api/yYxkv4eorhA/P-MHQOLA19MJ
+/* testing
+		function placeMarker() {
+			var cli = chart.getChartLayoutInterface();
+			document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+			var spot = Math.round(Math.max(25000 * Math.random(), 15000))
+			$('#pt_status').text(spot);
+			$('#spot').text(spot);
+			document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot)) + "px";
+		};
+
+
+		var cli = chart.getChartLayoutInterface();
+
+		var l= cli.getChartAreaBoundingBox().left;
+		var t=cli.getChartAreaBoundingBox().top;
+		var h=cli.getChartAreaBoundingBox().height;
+		var w= cli.getChartAreaBoundingBox().width;
+		var hx = cli.getYLocation(50000);
+		var cx = cli.getYLocation(0);
+
+		$('#pt_status').text(l + ':' + t  + ':' + h  + ':' + w + ':' + hx + ':' + cx);
+		  function chartMouseOver(e) {
+			var cli = chart.getChartLayoutInterface();
+			var xx = Math.floor(cli.getXLocation(e['row'])) + 'px';
+			var yy = Math.floor(cli.getYLocation(data.getValue(e['row'], 1))) + 'px';
+		  	$('#pt_status').text(e['row'] + ':' + xx +  + ':' + yy + ':' + data.getValue(e['row'], 1));
+		  	$('#pt2_status').text(e['row'] + ':' + cli.getHAxisValue(e['row']));
+		  }
+*/
+      } // end drawChart
+
+
+
+
+
+
+    </script>
+
+
+  </head>
+  <body>
+
+<div id='pt2_status'></div>
+<button type='button' id='b1'>Update</button>
+<div id="chart_div" style="width: 900px; height: 800px;"></div>
+<div id="barchart_div" style="width:800px; height: 600px;"></div>
+<div id='temp'></div>
+  <div class="overlay-marker">
+  <img src="/public/green_marker.png" height="50"><div id='spot'></div>
+  </div>
+
+<div id='pt_status'></div>
+  </body>
+</html>
+

+ 245 - 0
html/bubble-port-with-tabs.html

@@ -0,0 +1,245 @@
+<html>
+  <head>
+   <style>
+   .chartWithMarkerOverlay {
+       position: relative;
+       width: 700px;
+   }
+   .overlay-text {
+       width: 200px;
+       height: 200px;
+       position: absolute;
+       top: 30px;   /* chartArea top */
+       left: 200px; /* chartArea left */
+   }
+   .overlay-marker {
+       width: 50px;
+       height: 50px;
+       position: absolute;
+       top: 375px;   /* chartArea top */
+       left: 350px; /* chartArea left */
+       color: #000066;
+       font: 15px arial;
+    
+   }
+   </style>
+  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
+    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+
+<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
+<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
+
+    <script type="text/javascript">
+
+      google.load("visualization", "1.1", {packages:['corechart']});
+      google.setOnLoadCallback(drawChart);
+      function drawChart() {
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// guage functions
+
+
+		var data = google.visualization.arrayToDataTable( 
+{{{bubble_data}}}
+		); 
+
+
+		var options = { title: 'Portfolio Risk Distribution', 
+			hAxis: {title: 'Strike Price'}, vAxis: {title: ' Unreal P/L'}, 
+			// to display labels, remove the color: 'none option
+			bubble: {textStyle: {fontSize: 11, color: 'none'}}, colorAxis: {colors: ['red', 'blue']},
+			sizeAxis: {minValue: 2,  maxSize: 40}
+			//backgroundColor: '#E4E4E4'
+		 }; 
+
+
+		var chart = new google.visualization.BubbleChart(document.getElementById('chart_div')); 
+		chart.draw(data, options); 
+
+
+		google.visualization.events.addListener(chart, 'ready', placeIndexMarker);
+		
+		var button = document.getElementById('b1');
+
+		button.onclick = function() {
+			refreshPortItems();
+			refreshAcctItems();
+
+		}
+
+		setInterval(function() {
+		  placeIndexMarker();
+		}, 2000);
+
+
+
+		function refreshPortItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_bubble_data',
+			success: function (s_portitems) {
+
+
+				$('#pt_status').text(s_portitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				data = google.visualization.arrayToDataTable(eval(s_portitems));
+				chart.draw(data, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+
+		function refreshAcctItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_acct_data',
+			success: function (s_accttitems) {
+
+
+				$('#pt_status').text(s_accttitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				dataB = google.visualization.arrayToDataTable(eval(s_accttitems));
+				chart.draw(dataB, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+		function placeIndexMarker(){
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_market_data?r_ckey={{{FUT_CONTRACT}}}&fid=4',
+			success: function (data) {
+
+				var spot = data
+				$('#spot').text(spot);
+
+				var cli = chart.getChartLayoutInterface();
+				document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+				document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot) - 25) + "px";
+
+			}
+		    });
+
+
+		var dataB = google.visualization.arrayToDataTable(
+{{{barAcct}}}
+		);
+
+		var view = new google.visualization.DataView(dataB);
+		view.setColumns([0, 1,
+			       { calc: "stringify",
+				 sourceColumn: 1,
+				 type: "string",
+				 role: "annotation" }, 2]);
+
+		var options = {
+		chart: {
+		  title: 'Account Summary {{{account_no}}}',
+		  subtitle: 'Last updated {{{last_updated}}}'
+		},
+
+		bars: 'horizontal',bar: {groupWidth: "55%"},
+
+		  legend: { position: "none" },
+		};
+		var material = new google.visualization.BarChart(document.getElementById('barchart_div'));
+		material.draw(view, options);
+
+		}
+
+
+
+//https://groups.google.com/forum/#!msg/google-chart-api/yYxkv4eorhA/P-MHQOLA19MJ
+/* testing
+		function placeMarker() {
+			var cli = chart.getChartLayoutInterface();
+			document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+			var spot = Math.round(Math.max(25000 * Math.random(), 15000))
+			$('#pt_status').text(spot);
+			$('#spot').text(spot);
+			document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot)) + "px";
+		};
+
+
+		var cli = chart.getChartLayoutInterface();
+
+		var l= cli.getChartAreaBoundingBox().left;
+		var t=cli.getChartAreaBoundingBox().top;
+		var h=cli.getChartAreaBoundingBox().height;
+		var w= cli.getChartAreaBoundingBox().width;
+		var hx = cli.getYLocation(50000);
+		var cx = cli.getYLocation(0);
+
+		$('#pt_status').text(l + ':' + t  + ':' + h  + ':' + w + ':' + hx + ':' + cx);
+		  function chartMouseOver(e) {
+			var cli = chart.getChartLayoutInterface();
+			var xx = Math.floor(cli.getXLocation(e['row'])) + 'px';
+			var yy = Math.floor(cli.getYLocation(data.getValue(e['row'], 1))) + 'px';
+		  	$('#pt_status').text(e['row'] + ':' + xx +  + ':' + yy + ':' + data.getValue(e['row'], 1));
+		  	$('#pt2_status').text(e['row'] + ':' + cli.getHAxisValue(e['row']));
+		  }
+*/
+      } // end drawChart
+
+
+
+
+
+
+    </script>
+    <script>
+	$(function() {
+		$( "#tabs" ).tabs();
+	});
+    </script>
+
+  </head>
+  <body>
+<div id="tabs">
+  <ul>
+    <li><a href="#tabs-1">Dashboard</a></li>
+    <li><a href="#tabs-2">Position Distribution</a></li>
+    <li><a href="#tabs-3">Risk Distribution</a></li>
+  </ul>
+  <div id="tabs-1">
+	<div id='pt2_status'></div>
+	<button type='button' id='b1'>Update</button>
+	<div id="chart_div" style="width: 900px; height: 800px;"></div>
+	  <div class="overlay-marker">
+	  <img src="/public/green_marker.png" height="50"><div id='spot'></div>
+	  </div>
+
+
+  </div>
+
+  <div id="tabs-2">
+	<div id="barchart_div" style="width:800px; height: 600px;"></div>    
+  </div>
+
+
+  <div id="tabs-3">
+<div id='temp'></div>
+
+<div id='pt_status'></div>
+
+  </div>
+</div>
+
+  </body>
+</html>
+
+
+  </body>
+</html>
+

+ 222 - 0
html/bubble-port-with-tabs.html~

@@ -0,0 +1,222 @@
+<html>
+  <head>
+   <style>
+   .chartWithMarkerOverlay {
+       position: relative;
+       width: 700px;
+   }
+   .overlay-text {
+       width: 200px;
+       height: 200px;
+       position: absolute;
+       top: 30px;   /* chartArea top */
+       left: 200px; /* chartArea left */
+   }
+   .overlay-marker {
+       width: 50px;
+       height: 50px;
+       position: absolute;
+       top: 375px;   /* chartArea top */
+       left: 350px; /* chartArea left */
+       color: #000066;
+       font: 15px arial;
+    
+   }
+   </style>
+  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
+    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+
+<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
+<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
+
+    <script type="text/javascript">
+
+      google.load("visualization", "1.1", {packages:['corechart']});
+      google.setOnLoadCallback(drawChart);
+      function drawChart() {
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// guage functions
+
+
+		var data = google.visualization.arrayToDataTable( 
+{{{bubble_data}}}
+		); 
+
+
+		var options = { title: 'Portfolio Risk Distribution', 
+			hAxis: {title: 'Strike Price'}, vAxis: {title: ' Unreal P/L'}, 
+			// to display labels, remove the color: 'none option
+			bubble: {textStyle: {fontSize: 11, color: 'none'}}, colorAxis: {colors: ['red', 'blue']},
+			sizeAxis: {minValue: 2,  maxSize: 40}
+			//backgroundColor: '#E4E4E4'
+		 }; 
+
+
+		var chart = new google.visualization.BubbleChart(document.getElementById('chart_div')); 
+		chart.draw(data, options); 
+
+
+		google.visualization.events.addListener(chart, 'ready', placeIndexMarker);
+		
+		var button = document.getElementById('b1');
+
+		button.onclick = function() {
+			refreshPortItems();
+			refreshAcctItems();
+
+		}
+
+		setInterval(function() {
+		  placeIndexMarker();
+		}, 2000);
+
+
+
+		function refreshPortItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_bubble_data',
+			success: function (s_portitems) {
+
+
+				$('#pt_status').text(s_portitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				data = google.visualization.arrayToDataTable(eval(s_portitems));
+				chart.draw(data, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+
+		function refreshAcctItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_acct_data',
+			success: function (s_accttitems) {
+
+
+				$('#pt_status').text(s_accttitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				dataB = google.visualization.arrayToDataTable(eval(s_accttitems));
+				chart.draw(dataB, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+		function placeIndexMarker(){
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_market_data?r_ckey={{{FUT_CONTRACT}}}&fid=4',
+			success: function (data) {
+
+				var spot = data
+				$('#spot').text(spot);
+
+				var cli = chart.getChartLayoutInterface();
+				document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+				document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot) - 25) + "px";
+
+			}
+		    });
+
+
+		var dataB = google.visualization.arrayToDataTable(
+{{{barAcct}}}
+		);
+
+		var view = new google.visualization.DataView(dataB);
+		view.setColumns([0, 1,
+			       { calc: "stringify",
+				 sourceColumn: 1,
+				 type: "string",
+				 role: "annotation" }, 2]);
+
+		var options = {
+		chart: {
+		  title: 'Account Summary {{{account_no}}}',
+		  subtitle: 'Last updated {{{last_updated}}}'
+		},
+
+		bars: 'horizontal',bar: {groupWidth: "55%"},
+
+		  legend: { position: "none" },
+		};
+		var material = new google.visualization.BarChart(document.getElementById('barchart_div'));
+		material.draw(view, options);
+
+		}
+
+
+
+//https://groups.google.com/forum/#!msg/google-chart-api/yYxkv4eorhA/P-MHQOLA19MJ
+/* testing
+		function placeMarker() {
+			var cli = chart.getChartLayoutInterface();
+			document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+			var spot = Math.round(Math.max(25000 * Math.random(), 15000))
+			$('#pt_status').text(spot);
+			$('#spot').text(spot);
+			document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot)) + "px";
+		};
+
+
+		var cli = chart.getChartLayoutInterface();
+
+		var l= cli.getChartAreaBoundingBox().left;
+		var t=cli.getChartAreaBoundingBox().top;
+		var h=cli.getChartAreaBoundingBox().height;
+		var w= cli.getChartAreaBoundingBox().width;
+		var hx = cli.getYLocation(50000);
+		var cx = cli.getYLocation(0);
+
+		$('#pt_status').text(l + ':' + t  + ':' + h  + ':' + w + ':' + hx + ':' + cx);
+		  function chartMouseOver(e) {
+			var cli = chart.getChartLayoutInterface();
+			var xx = Math.floor(cli.getXLocation(e['row'])) + 'px';
+			var yy = Math.floor(cli.getYLocation(data.getValue(e['row'], 1))) + 'px';
+		  	$('#pt_status').text(e['row'] + ':' + xx +  + ':' + yy + ':' + data.getValue(e['row'], 1));
+		  	$('#pt2_status').text(e['row'] + ':' + cli.getHAxisValue(e['row']));
+		  }
+*/
+      } // end drawChart
+
+
+
+
+
+
+    </script>
+    <script>
+	$(function() {
+		$( "#tabs" ).tabs();
+	});
+    </script>
+
+  </head>
+  <body>
+
+<div id='pt2_status'></div>
+<button type='button' id='b1'>Update</button>
+<div id="chart_div" style="width: 900px; height: 800px;"></div>
+<div id="barchart_div" style="width:800px; height: 600px;"></div>
+<div id='temp'></div>
+  <div class="overlay-marker">
+  <img src="/public/green_marker.png" height="50"><div id='spot'></div>
+  </div>
+
+<div id='pt_status'></div>
+  </body>
+</html>
+

+ 81 - 7
html/bubble-port.html

@@ -16,8 +16,8 @@
        width: 50px;
        height: 50px;
        position: absolute;
-       top: 53px;   /* chartArea top */
-       left: 528px; /* chartArea left */
+       top: 375px;   /* chartArea top */
+       left: 350px; /* chartArea left */
        color: #000066;
        font: 15px arial;
     
@@ -57,7 +57,13 @@
 
 		google.visualization.events.addListener(chart, 'ready', placeIndexMarker);
 		
+		var button = document.getElementById('b1');
 
+		button.onclick = function() {
+			refreshPortItems();
+			refreshAcctItems();
+
+		}
 
 		setInterval(function() {
 		  placeIndexMarker();
@@ -65,7 +71,46 @@
 
 
 
-		function placeIndexMarker() {
+		function refreshPortItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_bubble_data',
+			success: function (s_portitems) {
+
+
+				//$('#pt_status').text(s_portitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				data = google.visualization.arrayToDataTable(eval(s_portitems));
+				chart.draw(data, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+
+		function refreshAcctItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_acct_data',
+			success: function (s_accttitems) {
+
+
+				//$('#pt_status').text(s_accttitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				dataB = google.visualization.arrayToDataTable(eval(s_accttitems));
+				chart.draw(dataB, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+		function placeIndexMarker(){
 		    $.ajax({
 			type: 'Post',
 			url: '/ws_market_data?r_ckey={{{FUT_CONTRACT}}}&fid=4',
@@ -75,14 +120,39 @@
 				$('#spot').text(spot);
 
 				var cli = chart.getChartLayoutInterface();
-				document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 45) + "px";
-				document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot)) + "px";
+				document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+				document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot) - 25) + "px";
 
 			}
 		    });
-		}
 
 
+		var dataB = google.visualization.arrayToDataTable(
+{{{barAcct}}}
+		);
+
+		var view = new google.visualization.DataView(dataB);
+		view.setColumns([0, 1,
+			       { calc: "stringify",
+				 sourceColumn: 1,
+				 type: "string",
+				 role: "annotation" }, 2]);
+
+		var options = {
+		chart: {
+		  title: 'Account Summary {{{account_no}}}',
+		  subtitle: 'Last updated {{{last_updated}}}'
+		},
+
+		bars: 'horizontal',bar: {groupWidth: "55%"},
+
+		  legend: { position: "none" },
+		};
+		var material = new google.visualization.BarChart(document.getElementById('barchart_div'));
+		material.draw(view, options);
+
+		}
+
 
 
 //https://groups.google.com/forum/#!msg/google-chart-api/yYxkv4eorhA/P-MHQOLA19MJ
@@ -127,13 +197,17 @@
 
   </head>
   <body>
-<div id='pt_status'></div>
+
 <div id='pt2_status'></div>
+<button type='button' id='b1'>Update Charts</button>
 <div id="chart_div" style="width: 900px; height: 800px;"></div>
+<div id="barchart_div" style="width:800px; height: 600px;"></div>
 <div id='temp'></div>
   <div class="overlay-marker">
   <img src="/public/green_marker.png" height="50"><div id='spot'></div>
   </div>
+
+<div id='pt_status'></div>
   </body>
 </html>
 

+ 83 - 9
html/bubble-port.html~

@@ -16,8 +16,8 @@
        width: 50px;
        height: 50px;
        position: absolute;
-       top: 53px;   /* chartArea top */
-       left: 528px; /* chartArea left */
+       top: 375px;   /* chartArea top */
+       left: 350px; /* chartArea left */
        color: #000066;
        font: 15px arial;
     
@@ -57,15 +57,60 @@
 
 		google.visualization.events.addListener(chart, 'ready', placeIndexMarker);
 		
+		var button = document.getElementById('b1');
+
+		button.onclick = function() {
+			refreshPortItems();
+			refreshAcctItems();
+
+		}
 
-/*
 		setInterval(function() {
 		  placeIndexMarker();
 		}, 2000);
-*/
 
 
-		function placeIndexMarker() {
+
+		function refreshPortItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_bubble_data',
+			success: function (s_portitems) {
+
+
+				$('#pt_status').text(s_portitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				data = google.visualization.arrayToDataTable(eval(s_portitems));
+				chart.draw(data, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+
+		function refreshAcctItems() {
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_acct_data',
+			success: function (s_accttitems) {
+
+
+				$('#pt_status').text(s_accttitems);				
+				//alert(jdata.delta_all);
+				lst = eval(s_portitems);
+//alert(lst[0]);
+				dataB = google.visualization.arrayToDataTable(eval(s_accttitems));
+				chart.draw(dataB, options);
+				drawChart();
+
+			}
+		    });
+		}
+
+		function placeIndexMarker(){
 		    $.ajax({
 			type: 'Post',
 			url: '/ws_market_data?r_ckey={{{FUT_CONTRACT}}}&fid=4',
@@ -75,14 +120,39 @@
 				$('#spot').text(spot);
 
 				var cli = chart.getChartLayoutInterface();
-				document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 45) + "px";
-				document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot)) + "px";
+				document.querySelector('.overlay-marker').style.top = Math.floor(cli.getYLocation(0) - 25) + "px";
+				document.querySelector('.overlay-marker').style.left = Math.floor(cli.getXLocation(spot) - 25) + "px";
 
 			}
 		    });
-		}
 
 
+		var dataB = google.visualization.arrayToDataTable(
+{{{barAcct}}}
+		);
+
+		var view = new google.visualization.DataView(dataB);
+		view.setColumns([0, 1,
+			       { calc: "stringify",
+				 sourceColumn: 1,
+				 type: "string",
+				 role: "annotation" }, 2]);
+
+		var options = {
+		chart: {
+		  title: 'Account Summary {{{account_no}}}',
+		  subtitle: 'Last updated {{{last_updated}}}'
+		},
+
+		bars: 'horizontal',bar: {groupWidth: "55%"},
+
+		  legend: { position: "none" },
+		};
+		var material = new google.visualization.BarChart(document.getElementById('barchart_div'));
+		material.draw(view, options);
+
+		}
+
 
 
 //https://groups.google.com/forum/#!msg/google-chart-api/yYxkv4eorhA/P-MHQOLA19MJ
@@ -127,13 +197,17 @@
 
   </head>
   <body>
-<div id='pt_status'></div>
+
 <div id='pt2_status'></div>
+<button type='button' id='b1'>Update Charts</button>
 <div id="chart_div" style="width: 900px; height: 800px;"></div>
+<div id="barchart_div" style="width:800px; height: 600px;"></div>
 <div id='temp'></div>
   <div class="overlay-marker">
   <img src="/public/green_marker.png" height="50"><div id='spot'></div>
   </div>
+
+<div id='pt_status'></div>
   </body>
 </html>
 

+ 2 - 1
sh/port_stream.sh

@@ -8,6 +8,7 @@ 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   $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