Răsfoiți Sursa

add gauge indicators

larry 10 ani în urmă
părinte
comite
115d753595

+ 69 - 39
cep/port_stream.py

@@ -12,7 +12,7 @@ import time
 import os
 #from finopt import ystockquote
 from comms.epc import ExternalProcessComm
-
+import ConfigParser
  
 ##
 ##
@@ -41,7 +41,6 @@ print sys.path
 #import optcal
 import json
 import numpy
-#from finopt.cep.redisQueue import RedisQueue
 from comms.redisQueue import RedisQueue
 from comms.alert_bot import AlertHelper
 
@@ -56,7 +55,7 @@ def f1(time, rdd):
     f = open('/home/larry/l1304/workspace/finopt/data/mds_files/std/std-20151007.txt', 'a') # % datetime.datetime.now().strftime('%Y%m%d%H%M'), 'a')
     msg = ''.join('%s,%s,%s,%s,%s\n'%(s[0], s[1][0][0].strftime('%Y-%m-%d %H:%M:%S.%f'),s[1][0][1],s[1][0][2], s[1][1]) for s in lt)
     f.write(msg)
-    d = Q.value
+    d = Param.value
     
     # return rdd tuple (-,((-,-),-)): name = 0--, time 100, sd 101, mean 102, vol 11-
     
@@ -74,16 +73,17 @@ def f1(time, rdd):
 def f2(time, rdd):
     lt =  rdd.collect()
     if lt:
-        change = lt[0][0]
-        d = Q.value
+        
+        param = Param.value
+        
         print '********** f2'
-        print lt[0][0], Threshold.value, lt[0][1]
+        
         print '********** end f2'
 
         
-        if change > Threshold.value:
-            msg = 'Stock alert triggered: %0.6f, mean: %0.2f' % (change, lt[0][1])
-            print msg
+#         if change > Threshold.value:
+#             msg = 'Stock alert triggered: %0.6f, mean: %0.2f' % (change, lt[0][1])
+#             print msg
 #             q = RedisQueue(d['alert_bot_q'][1], d['alert_bot_q'][0], d['host'], d['port'], d['db'])
 #             q.put(msg)
     
@@ -101,16 +101,42 @@ def f2(time, rdd):
 # 
 
 if __name__ == "__main__":
-    if len(sys.argv) != 5:
-        print("Usage: %s <broker_list ex: vsu-01:2181>  " % sys.argv[0])
-        print("Usage: to gracefully shutdown type echo 1 > /tmp/flag at the terminal")
-        exit(-1)
+#     if len(sys.argv) != 5:
+#         print("Usage: %s <broker_list ex: vsu-01:2181>  " % sys.argv[0])
+#         print("Usage: to gracefully shutdown type echo 1 > /tmp/flag at the terminal")
+#         exit(-1)
 
+    if len(sys.argv) != 5:
+        print("Usage: %s <config file>" % sys.argv[0])
+        exit(-1)    
+
+    cfg_path= sys.argv[1:]    
+    config = ConfigParser.ConfigParser()
+
+    param = {}
+    param['broker'] = 'vsu-1:2181'
+    param['app_name'] = "portfolio.stream" 
+    param['stream_interval'] = 5
+    param['win_interval'] = 20
+    param['slide_interval'] = 10
+    param['checkpoint_path'] = '/home/larry-13.04/workspace/finopt/log/checkpoint'
+    param['ib_contracts'] = ['HSI-20151029-0--FUT-HKD-102', 'HSI-20151127-0--FUT-HKD-102']
+    param['port_thresholds'] = {'delta_all': [-20.0, 20.0, -0.5, 0.75], 'delta_c': [-20.0, 20.0],
+                                'delta_p': [-20.0, 20.0],
+                                'theta_all': [2000.0, 7000.0], 'theta_c': [-20.0, 20.0],
+                                'theta_p': [-20.0, 20.0], 'unreal_pl': [-3]  
+                                }
 
-    app_name = "portfolio.stream"
-    sc = SparkContext(appName= app_name) #, pyFiles = ['./cep/redisQueue.py'])
-    ssc = StreamingContext(sc, 5)
-    ssc.checkpoint('/home/larry-13.04/workspace/finopt/log/checkpoint')
+    
+    param['rhost'] = config.get("redis", "redis.server").strip('"').strip("'")
+    param['rport'] = config.get("redis", "redis.port")
+    param['rdb'] = config.get("redis", "redis.db")
+    param['chatq'] = config.get("alert_bot", "msg_bot.redis_mq").strip('"').strip("'")
+    param['prefix'] = config.get("alert_bot", "msg_bot.redis_prefix").strip('"').strip("'")
+     
+    sc = SparkContext(appName= param['app_name']) #, pyFiles = ['./cep/redisQueue.py'])
+    ssc = StreamingContext(sc, param['stream_interval'])
+    ssc.checkpoint(param['checkpoint_path'])
 
 
 
@@ -118,29 +144,36 @@ if __name__ == "__main__":
     id = int(id)
     
 
-    NumProcessed = sc.accumulator(0)
     
+    Param = sc.broadcast(param)
     
-
+#                          { \
+#                       'rname': 'rname', 'qname': qname, 'namespace': 'mdq', 'host': 'localhost', 'port':6379, 'db': 3, 'alert_bot_q': ('alert_bot', 'chatq')})
     
-    Q = sc.broadcast({ \
-                      'rname': 'rname', 'qname': qname, 'namespace': 'mdq', 'host': 'localhost', 'port':6379, 'db': 3, 'alert_bot_q': ('alert_bot', 'chatq')})
     
+    # listen to portfolio updates sent by options_data.py
+    # via the EPC wrapper
+    port_st = KafkaUtils.createStream(ssc, param['broker'], param['app_name'], \
+                                  {v:1 for k,v in ExternalProcessComm.EPC_TOPICS.iteritems()}) 
+    # load the message into a dict
+    jport_st = port_st.map(lambda x: x[1]).map(lambda x: json.loads(x))
+    # split to new streams according to message types
+    pt_st = jport_st.filter(lambda x: x[1] == 'port_summary')\
+                .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'])
     
-#     s = {v:1 for k,v in ExternalProcessComm.EPC_TOPICS.iteritems()}
-#     print s
-    kvs = KafkaUtils.createStream(ssc, brokers, app_name, \
-                                  {v:1 for k,v in ExternalProcessComm.EPC_TOPICS.iteritems()}) #{'ib_tick_price':1, 'ib_tick_size':1})
-
-    lns = kvs.map(lambda x: x[1]).map(lambda x: json.loads(x))
-    ps = lns.filter(lambda x: x)
-    lns.pprint()
-#     ps = lns.map(lambda x: json.loads(x))\
-#             .filter(lambda x: (x['typeName'] == 'tickPrice'))\
-#             .map(lambda x: (x['contract'], (x['ts'], x['price']) ))\
-#             .groupByKeyAndWindow(12, 10, 1)
-# 
-#     sps.foreachRDD(f1)
+    
+    # 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)
+    
+    
+    #lns.pprint()
+ 
+    pt_st.foreachRDD(f2)
 # 
 #     sps.pprint()
     #trades.foreachRDD(eval(fn))
@@ -148,10 +181,7 @@ if __name__ == "__main__":
         
     def do_work():
 
-        while 1:
-            # program will stop after processing 40 rdds
-#             if NumProcessed.value == 70:
-#                 break            
+        while 1:       
             # program will stop on detecting a 1 in the flag file
             try:
                 f = open('/tmp/flag')

+ 15 - 7
comms/alert_bot.py

@@ -128,13 +128,16 @@ class AlertMsgBot(sleekxmpp.ClientXMPP):
 class AlertHelper():
     q = None
     
-    def __init__(self, config):
-        rhost = config.get("redis", "redis.server").strip('"').strip("'")
-        rport = config.get("redis", "redis.port")
-        rdb = config.get("redis", "redis.db")
-        chatq = config.get("alert_bot", "msg_bot.redis_mq").strip('"').strip("'")
-        prefix = config.get("alert_bot", "msg_bot.redis_prefix").strip('"').strip("'")
+    def __init__(self, config, rhost=None, rport=None, rdb=None, chatq=None, prefix=None):
+        if config:
+            rhost = config.get("redis", "redis.server").strip('"').strip("'")
+            rport = config.get("redis", "redis.port")
+            rdb = config.get("redis", "redis.db")
+            chatq = config.get("alert_bot", "msg_bot.redis_mq").strip('"').strip("'")
+            prefix = config.get("alert_bot", "msg_bot.redis_prefix").strip('"').strip("'")
         
+            
+            
         self.q = RedisQueue(chatq, prefix, rhost, rport, rdb)
         
     def post_msg(self, msg):
@@ -169,7 +172,12 @@ if __name__ == '__main__':
     if xmpp.connect(): #('192.168.1.1', 5222), True, True, False):
         xmpp.process(block=False)
         logging.info('Complete initialization...Bot will now run forever')
-        a = AlertHelper(config)
+        
+        # two different ways to instantiate alerthelper
+        cfg = {'rhost':'localhost', 'rport':6379, 'rdb': 3, 'chatq': 'chatq', 'prefix': 'alert_bot'}
+        a = AlertHelper(None, *cfg )
+        #a = AlertHelper(config)
+        
         i = a.flush_all()
         a.post_msg('from AlertHelper: flushed %d old messages.' % i)
         

BIN
comms/alert_bot.pyc


+ 1 - 0
config/app.cfg

@@ -19,6 +19,7 @@ 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'
  
 [/]
 tools.sessions.on : True

+ 62 - 0
finopt/opt_serve.py

@@ -367,6 +367,68 @@ class QServer(object):
         return s
     
     
+    @cherrypy.expose
+    def ws_port_summary(self):    
+        
+        rs = QServer.r_conn
+        ps_key = cherrypy.request.app.config['redis']['redis.datastore.key.port_summary']
+        s_portsum = rs.get(ps_key)
+        #dict = json.loads(s_portsum)
+        return s_portsum
+    
+
+    @cherrypy.expose
+    def ws_port_items(self):    
+        
+        rs = QServer.r_conn
+        key = cherrypy.request.app.config['redis']['redis.datastore.key.port_items']
+        s_portitems = rs.get(key)
+        #dict = json.loads(s_portsum)
+        return s_portitems
+    
+    
+    @cherrypy.expose
+    def port_bubble_chart(self):
+    
+        # Tick Value      Description
+        # 5001            impl vol
+        # 5002            delta
+        # 5003            gamma
+        # 5004            theta
+        # 5005            vega
+        # 5006            premium        
+        # 6001            avgCost
+        # 6002            pos
+        # 6003            totCost
+        # 6004            avgPx
+        # 6005            pos delta
+        # 6006            pos theta
+        # 6007            multiplier
+        # 6009            curr_port_value
+        # 6008            unreal_pl
+        # 6020            pos value impact +1% vol change
+        # 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)
+        
+        lpos_delta = map(lambda x: x['6005'], ldict)
+        lstrike = map(lambda x: x['contract'].split('-')[2], ldict)
+        ltheta = map(lambda x:  x['6006'], ldict)
+        lupl = map(lambda x: x['6008'], ldict)
+        
+        
+        
+        
+        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)))+ ']'
+        
+        print s_data
+        return s_data
+        
+    
     @cherrypy.expose
     def ws_msg_bot(self, msg):
         a = AlertHelper(self.config)

BIN
finopt/opt_serve.pyc


+ 1 - 1
finopt/options_data.py

@@ -887,7 +887,7 @@ class DataMap():
 #                                              [(contractTuple, m[0], t[2], 'C') for m in undly_months_prices])        
 #                 
                      s = p.recal_port()
-                     print s
+                     #print s
                     
             sleep(sec)
 

BIN
finopt/options_data.pyc


+ 11 - 5
finopt/portfolio.py

@@ -68,8 +68,12 @@ class PortfolioManager():
         self.rs_port_keys['port_conid_set'] = config.get("redis", "redis.datastore.key.port_conid_set").strip('"').strip("'")
         self.rs_port_keys['port_prefix'] = config.get("redis", "redis.datastore.key.port_prefix").strip('"').strip("'")        
         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.epc = eval(config.get("portfolio", "portfolio.epc").strip('"').strip("'"))
         # instantiate a epc object if the config says so
+        
+        
         if self.epc['stream_to_Kafka']:
             self.epc['epc'] = EPCPub(config) 
         
@@ -414,6 +418,7 @@ class PortfolioManager():
                 #print pmap
                 #print json.dumps(pmap)
                 self.r_set(ckey, json.dumps(pmap))
+                
                 logging.debug('PortfolioManager: update position in redis %s' % self.r_get(ckey))
                 
             else:
@@ -441,15 +446,16 @@ class PortfolioManager():
         #self.r_set(self.rs_port_keys['port_summary'], json.dumps(pos_summary) )
         t_pos_summary = json.dumps(pos_summary)
         self.r_conn.set(self.rs_port_keys['port_summary'], t_pos_summary )
-  
+        self.r_conn.set(self.rs_port_keys['port_items'], json.dumps(l_gmap))
         #print pos_summary
         #print l_gmap      
         # broadcast 
         if self.epc['epc']:
-            
-            self.epc['epc'].post_portfolio_summary(pos_summary)
-            self.epc['epc'].post_portfolio_items(l_gmap)
-        
+            try:
+                self.epc['epc'].post_portfolio_summary(pos_summary)
+                self.epc['epc'].post_portfolio_items(l_gmap)
+            except:
+                logging.exception("Exception in function: recal_port_rentrant_unsafe")
 
         #logging.info(pos_summary)
         

BIN
finopt/portfolio.pyc


+ 26 - 0
html/bubble.html

@@ -0,0 +1,26 @@
+    google.setOnLoadCallback(drawSeriesChart);
+
+    function drawSeriesChart() {
+
+      var data = google.visualization.arrayToDataTable(
+[['contract', 'strike', 'unreal PL', 'theta', 'delta'],["HSI-20151029-21800-C",21800,23919.9417517,-847.640353617,34.3206494687],["HSI-20151029-20600-P",20600,2370.18040195,234.030821339,2.94991041015],["HSI-20151029-18000-P",18000,669.979772265,16.7243718533,0.0961753807965],["MHI-20151029-22400-C",22400,4571.99658662,-653.903571555,21.3110103014],["HSI-20151029-20800-P",20800,0.0,-0.0,-0.0],["HSI-20151029-17000-P",17000,4469.99924749,17.2106407419,0.078741153585],["HSI-20151029-19400-P",19400,1090.19189451,157.899556569,1.30201821447],["HSI-20151029-24600-C",24600,1709.81965805,244.615050639,-3.28831913087],["HSI-20151029-18400-P",18400,2259.99903292,49.4722768455,0.315622642862],["HSI-20151029-22400-C",22400,0.0,-0.0,0.0],["HSI-20151029-19800-P",19800,9030.05297609,439.87608901,4.12517690941],["HSI-20151029-24800-C",24800,1539.95739179,95.3030785737,-1.20569112818],["HSI-20151029-24200-C",24200,9430.2283091,1626.16833327,-25.1547381539],["MHI-20151029-24200-C",24200,59.0205730977,108.601166314,-1.66956781611],["HSI-20151029-23400-C",23400,6582.44069705,2015.2933091,-42.9465063458],["MHI-20151029-21400-P",21400,-2587.99599722,-335.511655065,-6.28266480291],["HSI-20151029-23600-C",23600,-4590.04663309,1275.53162128,-24.8106720387],["MHI-20151029-22200-C",22200,5018.99635688,-510.749138578,17.6661251353],["HSI-20151029-23200-C",23200,-21315.899837,2954.43687153,-68.7130818343],["HSI-20151029-22200-C",22200,32039.9788834,-1677.02322083,59.3074230743],["HSI-20151029-19600-P",19600,1540.01810034,190.494158898,1.67062250645],["HSI-20151029-20400-P",20400,5841.11465835,390.360320296,4.54010718334],["HSI-20151029-20200-P",20200,8829.84904992,648.441667022,6.99051336801],["MHI-20151029-21000-P",21000,-47984.8017666,-455.612887365,-6.87918674625],["MHI-20151029-21000-C",21000,40535.0017735,-886.520963812,39.5681292655],["HSI-20151029-16600-P",16600,10509.9969485,52.1482807266,0.21982694595],]   
+      );
+
+      var options = {
+        title: 'Portfolio Risk Distribution',
+        hAxis: {title: 'Strikes'},
+        vAxis: {title: ' Unreal P/L'},
+        bubble: {textStyle: {fontSize: 11}},
+	colorAxis: {colors: ['red', 'blue']}
+
+      };
+
+      var chart = new google.visualization.BubbleChart(document.getElementById('series_chart_div'));
+      chart.draw(data, options);
+    }
+
+
+
+<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['corechart']}]}"></script>
+       <div id="series_chart_div" style="width: 900px; height: 900px;"></div>
+   

+ 96 - 0
html/opt-pos-chart-tmpl (copy).html

@@ -0,0 +1,96 @@
+<html>
+  <head>
+  <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:["bar", 'table']});
+//      google.load('visualization', '1', {'packages':['table']});
+//      google.load("visualization", "1.1", {packages:["corechart"]});
+      google.setOnLoadCallback(drawChart);
+      function drawChart() {
+        var data = google.visualization.arrayToDataTable([
+          ['Strike Price', 'P', 'C', ],
+{{{dataPCpos}}}
+        ]);
+
+	var dataTbl = google.visualization.arrayToDataTable([
+{{{dataTablePos}}}
+
+        ]);
+
+
+        var options = {
+          width: 900,
+          chart: {
+            title: 'Option Postion Distribution. PUT:CALL Ratio [{{{PRvsCR}}}}]',
+            subtitle: 'for the month of {{{option_months}}}',
+          },
+ 
+        };
+
+        var chart = new google.charts.Bar(document.getElementById('barchart_material'));
+        chart.draw(data, options);
+
+
+
+
+	// chart table display implied volatilities in a nicely formatted table	
+       var chartTbl = new google.visualization.Table(document.getElementById('chartTbl_div'));
+
+
+       var portTbl = new google.visualization.Table(document.getElementById('portTblDiv'));
+
+	var formatter = new google.visualization.NumberFormat({pattern:'0.00'});
+	for (var i = 2; i < 9; i++)
+		formatter.format(dataTbl, i); 
+        var options2 = {
+          displayAnnotations: true,
+	  showRowNumber: true, width: '100%', height: '100%', allowHtml: true,
+        };
+	chartTbl.draw(dataTbl, options2);
+
+	$('input[id="b_reload"]').click();
+
+      }
+
+
+//        $(document).ready(function () {
+		$('input[id="b_reload"]').click(function () {
+//		   var formatter = new google.visualization.NumberFormat({pattern:'0.00'});
+//		   for (var i = 0; i < 9; i++)
+//				formatter.format(portTbl, i); 
+		   var options3 = {
+			displayAnnotations: true,
+			showRowNumber: true, width: '100%', height: '100%', allowHtml: true,
+			};	    
+		    $.ajax({
+			type: 'Post',
+			url: '/ws_position_summary',
+			success: function (data) {
+alert(data);
+				var jdata = JSON.parse('{"rows": [{"v": 0.047488620928674306}, {"v": -34.1918070686455}, {"v": 35.01931221132403}, {"v": -69.21111927996955}, {"v": 0.0}, {"v": 4350.744926215475}, {"v": -297.6744472363985}, {"v": 4648.419373451876}, {"v": 89903.71832036527}, {"v": "20150915231057"}, {"v": "OK"}], "cols": [{"type": "number", "label": "delta_1percent"}, {"type": "number", "label": "delta_all"}, {"type": "number", "label": "delta_c"}, {"type": "number", "label": "delta_p"}, {"type": "number", "label": "theta_1percent"}, {"type": "number", "label": "theta_all"}, {"type": "number", "label": "theta_c"}, {"type": "number", "label": "theta_p"}, {"type": "number", "label": "unreal_pl"}, {"type": "string", "label": "last_updated"}, {"type": "string", "label": "status"}]}');
+
+				$('#temp').text(jdata);
+				var d  = new google.visualization.DataTable(jdata);
+				portTbl.draw(d, options3);
+			}
+		    });
+		})
+//	});
+
+    </script>
+
+
+  </head>
+  <body>
+    <div id="barchart_material" style="width: 900px; height: 500px;"></div>
+    <div id='chartTbl_div' style='width: 900px; height: 500px;'></div>
+    <div id="portTbl">
+        <input type="button" id="b_reload" value="Reload" />
+    </div>
+    <div id='portTblDiv' style='width: 900px; height: 500px;'></div>
+<div id='temp'></div>
+
+  </body>
+</html>
+

+ 95 - 19
html/opt-pos-chart-tmpl.html

@@ -3,7 +3,7 @@
   <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:["bar", 'table']});
+      google.load("visualization", "1.1", {packages:["bar", 'table','gauge']});
 //      google.load('visualization', '1', {'packages':['table']});
 //      google.load("visualization", "1.1", {packages:["corechart"]});
       google.setOnLoadCallback(drawChart);
@@ -38,7 +38,7 @@
        var chartTbl = new google.visualization.Table(document.getElementById('chartTbl_div'));
 
 
-       var portTbl = new google.visualization.Table(document.getElementById('portTblDiv'));
+       //var portTbl = new google.visualization.Table(document.getElementById('portTblDiv'));
 
 	var formatter = new google.visualization.NumberFormat({pattern:'0.00'});
 	for (var i = 2; i < 9; i++)
@@ -51,31 +51,103 @@
 
 	$('input[id="b_reload"]').click();
 
-      }
 
 
-//        $(document).ready(function () {
-		$('input[id="b_reload"]').click(function () {
-//		   var formatter = new google.visualization.NumberFormat({pattern:'0.00'});
-//		   for (var i = 0; i < 9; i++)
-//				formatter.format(portTbl, i); 
-		   var options3 = {
-			displayAnnotations: true,
-			showRowNumber: true, width: '100%', height: '100%', allowHtml: true,
-			};	    
+////////////////////////////////////////////////////////////////////////////////
+// guage functions
+
+		var dataG = google.visualization.arrayToDataTable([
+		  ['Label', 'Value'],
+		  ['Delta', 0],
+		  ['Delta-C', 0],
+		  ['Delta-P', 0]
+		]);
+
+		var optionsG = {
+
+		  width: 400, height: 120,
+		  redFrom: -50, redTo: -25,
+		  yellowFrom:-24, yellowTo: -15,
+		  greenFrom: -10, greenTo: 10,	
+		  minorTicks: 5,
+		  min: -50, max: 50
+		};
+
+		var dataT = google.visualization.arrayToDataTable([
+		  ['Label', 'Value'],
+		  ['Theta', 0],
+		  ['Theta-C', 0],
+		  ['Theta-P', 0]
+		]);
+
+		var optionsT = {
+
+		  width: 400, height: 120,
+		  redFrom: -3000, redTo: -2000,
+		  yellowFrom:-1999, yellowTo: 500,
+		  greenFrom: 5000, greenTo: 15000,	
+		  minorTicks: 5,
+		  min: -3000, max: 15000
+		};
+
+		var gchart = new google.visualization.Gauge(document.getElementById('chart_div'));
+//		refreshPortSummary();
+//		gchart.draw(dataG, optionsG);
+
+		var tchart = new google.visualization.Gauge(document.getElementById('chartTheta_div'));
+		refreshPortSummary();
+		
+		function refreshPortSummary(){
 		    $.ajax({
 			type: 'Post',
-			url: '/ws_position_summary',
+			url: '/ws_port_summary',
 			success: function (data) {
-alert(data);
-				var jdata = JSON.parse('{"rows": [{"v": 0.047488620928674306}, {"v": -34.1918070686455}, {"v": 35.01931221132403}, {"v": -69.21111927996955}, {"v": 0.0}, {"v": 4350.744926215475}, {"v": -297.6744472363985}, {"v": 4648.419373451876}, {"v": 89903.71832036527}, {"v": "20150915231057"}, {"v": "OK"}], "cols": [{"type": "number", "label": "delta_1percent"}, {"type": "number", "label": "delta_all"}, {"type": "number", "label": "delta_c"}, {"type": "number", "label": "delta_p"}, {"type": "number", "label": "theta_1percent"}, {"type": "number", "label": "theta_all"}, {"type": "number", "label": "theta_c"}, {"type": "number", "label": "theta_p"}, {"type": "number", "label": "unreal_pl"}, {"type": "string", "label": "last_updated"}, {"type": "string", "label": "status"}]}');
+				//alert(data);
+				var jdata = JSON.parse(data);
+				$('#temp').text(data);				
+				//alert(jdata.delta_all);
+				
+				dataG.setValue(0, 1, Math.round(jdata.delta_all*100)/100);
+				dataG.setValue(1, 1, Math.round(jdata.delta_c*100)/100);
+				dataG.setValue(2, 1, Math.round(jdata.delta_p*100)/100);
+				gchart.draw(dataG, optionsG);
+
+				dataT.setValue(0, 1, Math.round(jdata.theta_all));
+				dataT.setValue(1, 1, Math.round(jdata.theta_c));
+				dataT.setValue(2, 1, Math.round(jdata.theta_p));
+				tchart.draw(dataT, optionsT);
+
+				$('#pt_status').text("Unreal P/L: " + Math.round(jdata.unreal_pl*100)/100 + "   Cal Status: " + jdata.status);
 
-				$('#temp').text(jdata);
-				var d  = new google.visualization.DataTable(jdata);
-				portTbl.draw(d, options3);
 			}
 		    });
-		})
+
+		};
+
+		setInterval(function() {
+			refreshPortSummary();
+		}, 9500);    
+
+
+
+
+
+
+
+
+      } // end drawChart
+
+
+
+
+
+
+
+	
+
+
+		//})
+
 //	});
 
     </script>
@@ -83,6 +155,10 @@ alert(data);
 
   </head>
   <body>
+<div id='pt_status'></div>
+<div id="chart_div" style="width: 400px; height: 120px;"></div>
+<div id="chartTheta_div" style="width: 400px; height: 120px;"></div>
+
     <div id="barchart_material" style="width: 900px; height: 500px;"></div>
     <div id='chartTbl_div' style='width: 900px; height: 500px;'></div>
     <div id="portTbl">

+ 99 - 21
html/opt-pos-chart-tmpl.html~

@@ -3,8 +3,8 @@
   <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:["bar"]});
-      google.load('visualization', '1', {'packages':['table']});
+      google.load("visualization", "1.1", {packages:["bar", 'table','gauge']});
+//      google.load('visualization', '1', {'packages':['table']});
 //      google.load("visualization", "1.1", {packages:["corechart"]});
       google.setOnLoadCallback(drawChart);
       function drawChart() {
@@ -38,7 +38,7 @@
        var chartTbl = new google.visualization.Table(document.getElementById('chartTbl_div'));
 
 
-       var portTbl = new google.visualization.Table(document.getElementById('portTblDiv'));
+       //var portTbl = new google.visualization.Table(document.getElementById('portTblDiv'));
 
 	var formatter = new google.visualization.NumberFormat({pattern:'0.00'});
 	for (var i = 2; i < 9; i++)
@@ -51,38 +51,116 @@
 
 	$('input[id="b_reload"]').click();
 
-      }
 
 
-        $(document).ready(function () {
-		$('input[id="b_reload"]').click(function () {
-//		   var formatter = new google.visualization.NumberFormat({pattern:'0.00'});
-//		   for (var i = 0; i < 9; i++)
-//				formatter.format(portTbl, i); 
-		   var options3 = {
-			displayAnnotations: true,
-			showRowNumber: true, width: '100%', height: '100%', allowHtml: true,
-			};	    
+////////////////////////////////////////////////////////////////////////////////
+// guage functions
+
+		var dataG = google.visualization.arrayToDataTable([
+		  ['Label', 'Value'],
+		  ['Delta', 0],
+		  ['Delta-C', 0],
+		  ['Delta-P', 0]
+		]);
+
+		var optionsG = {
+		  chart:{
+			  title: 'Portfolio Delta Value'}, 
+		  width: 400, height: 120,
+		  redFrom: -50, redTo: -25,
+		  yellowFrom:-24, yellowTo: -15,
+		  greenFrom: -10, greenTo: 10,	
+		  minorTicks: 5,
+		  min: -50, max: 50
+		};
+
+		var dataT = google.visualization.arrayToDataTable([
+		  ['Label', 'Value'],
+		  ['Theta', 0],
+		  ['Theta-C', 0],
+		  ['Theta-P', 0]
+		]);
+
+		var optionsT = {
+		  chart:{
+		  	title: 'Portfolio Theta Value'},
+		  width: 400, height: 120,
+		  redFrom: -3000, redTo: -2000,
+		  yellowFrom:-1999, yellowTo: 500,
+		  greenFrom: 5000, greenTo: 15000,	
+		  minorTicks: 5,
+		  min: -3000, max: 15000
+		};
+
+		var gchart = new google.visualization.Gauge(document.getElementById('chart_div'));
+//		refreshPortSummary();
+//		gchart.draw(dataG, optionsG);
+
+		var tchart = new google.visualization.Gauge(document.getElementById('chartTheta_div'));
+		refreshPortSummary();
+		
+		function refreshPortSummary(){
 		    $.ajax({
 			type: 'Post',
-			url: '/ws_position_summary',
+			url: '/ws_port_summary',
 			success: function (data) {
-alert(data);
-				var jdata = JSON.parse('{"rows": [{"v": 0.047488620928674306}, {"v": -34.1918070686455}, {"v": 35.01931221132403}, {"v": -69.21111927996955}, {"v": 0.0}, {"v": 4350.744926215475}, {"v": -297.6744472363985}, {"v": 4648.419373451876}, {"v": 89903.71832036527}, {"v": "20150915231057"}, {"v": "OK"}], "cols": [{"type": "number", "label": "delta_1percent"}, {"type": "number", "label": "delta_all"}, {"type": "number", "label": "delta_c"}, {"type": "number", "label": "delta_p"}, {"type": "number", "label": "theta_1percent"}, {"type": "number", "label": "theta_all"}, {"type": "number", "label": "theta_c"}, {"type": "number", "label": "theta_p"}, {"type": "number", "label": "unreal_pl"}, {"type": "string", "label": "last_updated"}, {"type": "string", "label": "status"}]}');
+				//alert(data);
+				var jdata = JSON.parse(data);
+				$('#temp').text(data);				
+				//alert(jdata.delta_all);
+				
+				dataG.setValue(0, 1, Math.round(jdata.delta_all*100)/100);
+				dataG.setValue(1, 1, Math.round(jdata.delta_c*100)/100);
+				dataG.setValue(2, 1, Math.round(jdata.delta_p*100)/100);
+				gchart.draw(dataG, optionsG);
+
+				dataT.setValue(0, 1, Math.round(jdata.theta_all));
+				dataT.setValue(1, 1, Math.round(jdata.theta_c));
+				dataT.setValue(2, 1, Math.round(jdata.theta_p));
+				tchart.draw(dataT, optionsT);
+
+				$('#pt_status').text("Unreal P/L: " + Math.round(jdata.unreal_pl*100)/100 + "   Cal Status: " + jdata.status);
 
-				$('#temp').text(jdata);
-				var d  = new google.visualization.DataTable(data);
-				portTbl.draw(d, options3);
 			}
 		    });
-		})
-	});
+
+		};
+
+		setInterval(function() {
+			refreshPortSummary();
+		}, 9500);    
+
+
+
+
+
+
+
+
+      } // end drawChart
+
+
+
+
+
+
+
+	
+
+
+		//})
+
+//	});
 
     </script>
 
 
   </head>
   <body>
+<div id='pt_status'></div>
+<div id="chart_div" style="width: 400px; height: 120px;"></div>
+<div id="chartTheta_div" style="width: 400px; height: 120px;"></div>
+
     <div id="barchart_material" style="width: 900px; height: 500px;"></div>
     <div id='chartTbl_div' style='width: 900px; height: 500px;'></div>
     <div id="portTbl">

+ 4 - 0
sh/portfolio.sh

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