浏览代码

holiday eve changes

bobhk 8 年之前
父节点
当前提交
3630a8e553
共有 5 个文件被更改,包括 91 次插入33 次删除
  1. 41 7
      src/rethink/portfolio_column_chart.py
  2. 1 1
      src/rethink/portfolio_item.py
  3. 34 24
      src/rethink/portfolio_monitor.py
  4. 14 0
      src/ws/client_g.html
  5. 1 1
      src/ws/ws_server.py

+ 41 - 7
src/rethink/portfolio_column_chart.py

@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-import sys, traceback, logging
+import sys, traceback, logging, json
 from rethink.portfolio_item import PortfolioRules, PortfolioItem, Portfolio
 import numpy as np
 from rethink.table_model import AbstractPortfolioTableModelListener, AbstractTableModel
@@ -39,9 +39,11 @@ class PortfolioColumnChart():
         self.xy_arr = None
         self.col_header = {'j_contract_to_col_num': None, 'j_contract_to_col_num_reverse': None}
         self.row_header = {'i_strike_to_row_num': None, 'i_strike_to_row_num_reverse': None}
+        self.last_tally = 0
+        self.never_been_run = True
     
     def get_object_name(self):
-        return 'p-%s' % (id(self))   
+        return json.dumps({'account': self.pf.account, 'id': id(), 'class': self.__class__.__name__})
     
     def ckey_to_row(self, contract_key):
         
@@ -57,7 +59,17 @@ class PortfolioColumnChart():
                 for i in self.xy_arr.shape[0]:
                     if self.xy_arr[i][col] <> 0:
                         return i
-        
+    
+    def update_tally_count(self):
+        self.last_tally = self.count_tally()
+    
+    
+    def get_xy_array(self):
+        return self.xy_arr
+    
+    
+    def get_last_tally(self):
+        return self.last_tally   
            
     def get_values_at(self, row):
         rf = [{'v': self.row_header['i_strike_to_row_num_reverse'][row]}]
@@ -70,6 +82,17 @@ class PortfolioColumnChart():
         return  '%s-%s-%s-%s' % (p_item.get_expiry(),  p_item.get_symbol_id(), 
                                                     p_item.get_instrument_type(), p_item.get_right() )  
     
+    
+    def count_tally(self):
+        p2_items = self.pf.get_portfolio_port_items().values()
+        p1_items = filter(lambda x: x.get_symbol_id() in PortfolioRules.rule_map['interested_position_types']['symbol'], p2_items)
+        p_items = filter(lambda x: x.get_instrument_type() in  PortfolioRules.rule_map['interested_position_types']['instrument_type'], p1_items)
+        try:
+            tally =  reduce(lambda x,y: x+y, map(lambda x: abs(x.get_quantity()), p_items))
+            return tally
+        except:
+            return 0
+    
     def get_JSON(self):  
         
         
@@ -105,7 +128,7 @@ class PortfolioColumnChart():
             i_strike_to_row_num_reverse[m] = i_strikes_range[m]
         
         #print '---xmap and xmap reverse' 
-        print i_strike_to_row_num
+        #print i_strike_to_row_num
         #print i_strike_to_row_num_reverse
         #print '---'
         
@@ -121,7 +144,7 @@ class PortfolioColumnChart():
             j_contract_to_col_num_reverse[n]= j_contract_types[n]  
         
 #         print '---ymap and ymap reverse' 
-        print j_contract_to_col_num
+        #print j_contract_to_col_num
 #         print j_contract_to_col_num_reverse
 #         print '----'
 
@@ -147,7 +170,7 @@ class PortfolioColumnChart():
             return (i,j,v)
         
         ijv_dist = map(set_ij, p_items)
-        print ijv_dist
+        
         xy_arr = np.zeros((len(i_strikes_range), len(j_contract_types)))
         
         
@@ -158,6 +181,7 @@ class PortfolioColumnChart():
         
         map(update_ijv, ijv_dist)
         print xy_arr
+        logging.info('PortfolioColumnChart: JSON array->\n%s' % xy_arr)
         
         def gen_datatable():
             ccj = {'cols':[{'id': 'strike', 'label': 'strike', 'type': 'number'}], 'rows':[]}
@@ -188,7 +212,9 @@ class PortfolioColumnChartTM(PortfolioColumnChart, AbstractTableModel, AbstractP
         self.kproducer = kproducer
         
         
-        
+    def get_kproducer(self):
+        return self.kproducer
+      
 #     def get_column_count(self):
 #         raise NotImplementedException
 #     
@@ -216,9 +242,17 @@ class PortfolioColumnChartTM(PortfolioColumnChart, AbstractTableModel, AbstractP
 
     def event_tm_table_structure_changed(self, event, source, origin_request_id, account, data_table_json):
         logging.info("[PortfolioColumnChartTM:%s] received %s content:[%s]" % (self.name, event, vars()))
+        
+        
     
     def event_tm_request_table_structure(self, event, request_id, target_resource, account):
         self.request_ids[request_id] = {'request_id': request_id, 'account': account}
         logging.info("[PortfolioColumnChartTM:%s] received %s content:[%s]" % (self.name, event, vars()))
+        if target_resource['class'] == self.get_object_name()['class']:
+            self.get_kproducer().send_message(AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED,                                               
+                                      json.dumps({'source': self.get_object_name(), 
+                                                  'origin_request_id': request_id, 'account': account, 
+                                                  'data_table_json': self.get_JSON()}))
+                
                
     

+ 1 - 1
src/rethink/portfolio_item.py

@@ -235,7 +235,7 @@ class Portfolio(AbstractTableModel):
         AbstractTableModel.__init__(self)
         
     def get_object_name(self):
-        return 'p-%s-%s' % (self.account, id(self))
+        return json.dumps({'account': self.account, 'id': id(), 'class': self.__class__.__name__})
     
     def is_contract_in_portfolio(self, contract_key):
         return self.get_portfolio_port_item(contract_key)

+ 34 - 24
src/rethink/portfolio_monitor.py

@@ -38,7 +38,7 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
             portfolios: {<account>: <portfolio>}
         '''
         self.portfolios = {}
-        self.starting_engine = {}
+        self.starting_engine = True
         
         
         '''
@@ -111,6 +111,7 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
                         for acct in self.portfolios.keys():
                             pc = PortfolioColumnChart(self.portfolios[acct])
                             print pc.get_JSON()
+                            print pc.get_xy_array()
                             
                     elif selection == '9': 
                         self.twsc.gw_message_handler.set_stop()
@@ -149,12 +150,9 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
                                                                      self.portfolios[account], 
                                                                      self.get_kproducer())
             self.portfolio_charts[account] = {'PortfolioColumnChartTM': pcc}
-                                              
-            print 'here2'
-            self.twsc.add_listener_topics(pcc, [AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED] )
-            print 'here3'
+            self.twsc.add_listener_topics(pcc, [AbstractTableModel.EVENT_TM_REQUEST_TABLE_STRUCTURE, AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED] )            
             logging.info('PortfoioMonitor:get_portfolio creating port and chart object...%s' % account)
-            print 'end'
+
         return self.portfolios[account]
     
     def deduce_option_underlying(self, option):
@@ -258,10 +256,7 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
             port.dump_portfolio()
             
             
-            
-            
-    def update(self, event, param=None):
-        logging.warn('***** no handler for event %s. Captured by the default handler: update() ****')            
+              
     
     #         EVENT_OPTION_UPDATED = 'oc_option_updated'
     #         EVENT_UNDERLYING_ADDED = 'oc_underlying_added
@@ -357,6 +352,7 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
         pass
  
     def position(self, event, account, contract_key, position, average_cost, end_batch):
+        
         if not end_batch:
             #logging.info('PortfolioMonitor:position. received position message contract=%s' % contract_key)
             self.process_position(account, contract_key, position, average_cost)
@@ -364,12 +360,11 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
         else:
             # to be run once per a/c during start up
             # subscribe to automatic account updates
-            try:
-                self.starting_engine[account]
-            except KeyError:
-                self.twsc.reqAccountUpdates(True, account)
-                logging.info('PortfolioMonitor:position. subscribing to auto updates for ac: [%s]' % account)  
-                self.starting_engine[account] = False
+            if self.starting_engine:
+                for acct in self.portfolios.keys():
+                    self.twsc.reqAccountUpdates(True, account)
+                    logging.info('PortfolioMonitor:position. subscribing to auto updates for ac: [%s]' % account)  
+                    self.starting_engine = False
                     
     '''
         the 4 account functions below are invoked by AbstractListener.update_portfolio_account.
@@ -415,13 +410,28 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
         # notify chart objects to do their thing...
         try:
             pcc = self.portfolio_charts[account]['PortfolioColumnChartTM']
-            if mode == 'I':
-                pcc.fire_table_structure_changed(AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED, 
-                                                 pcc.get_object_name(), None, account, pcc.get_JSON())
+            if self.starting_engine == False:
+                if pcc.never_been_run == True:
+                    pcc.fire_table_structure_changed(AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED, 
+                                                  pcc.get_object_name(), None, account, pcc.get_JSON())
+                    pcc.never_been_run = False
+                    logging.info('PortfolioMonitor:notify_table_model_changes. first time trigger columnchart %d' % pcc.get_last_tally())
+                elif pcc.get_last_tally() <> pcc.count_tally():
+                    pcc.fire_table_structure_changed(AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED, 
+                                                  pcc.get_object_name(), None, account, pcc.get_JSON())
+                    logging.info('PortfolioMonitor:notify_table_model_changes. tally count %d...dump json' % pcc.get_last_tally())
+                    pcc.update_tally_count()
             else:
-                row = pcc.ckey_to_row(contract_key)
-                rvs = pcc.get_values_at(row)
-                logging.info('PortfolioMonitor:notify_table_model_changes. PortfolioColumnChartTM %d' % row)
+                pcc.update_tally_count()
+                logging.info('PortfolioMonitor:notify_table_model_changes. tally count %d' % pcc.get_last_tally())
+#            if mode == 'I':
+#                 pcc.fire_table_structure_changed(AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED, 
+#                                                  pcc.get_object_name(), None, account, pcc.get_JSON())
+#            else:
+                
+#                 row = pcc.ckey_to_row(contract_key)
+#                 rvs = pcc.get_values_at(row)
+#                 logging.info('PortfolioMonitor:notify_table_model_changes. PortfolioColumnChartTM %d' % row)
                 #pcc.fire_table_row_updated(row, rvs)
                   
         except: # KeyError:
@@ -433,7 +443,8 @@ class PortfolioMonitor(AbstractGatewayListener, AbstractPortfolioTableModelListe
     # handle requests to get data table json
     def event_tm_request_table_structure(self, event, request_id, target_resource, account):
         try:
-            self.get_kproducer().send_message(AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED,                                               
+            if target_resource['class'] == 'Portfolio':
+                self.get_kproducer().send_message(AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED,                                               
                                           json.dumps({'source': self.portfolios[account].get_object_name(), 
                                                       'origin_request_id': request_id, 'account': account, 
                                                       'data_table_json': self.portfolios[account].get_JSON()}))
@@ -463,7 +474,6 @@ if __name__ == '__main__':
       'clear_offsets':  False,
       'logconfig': {'level': logging.INFO, 'filemode': 'w', 'filename': '/tmp/pm.log'},
       'topics': ['position', 'positionEnd', 'tickPrice', 'update_portfolio_account', 'event_tm_request_table_structure', AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED],
-      'tm_topics': [AbstractTableModel.EVENT_TM_TABLE_STRUCTURE_CHANGED, AbstractTableModel.EVENT_TM_REQUEST_TABLE_STRUCTURE],
       'seek_to_end': ['*'],
       
       

+ 14 - 0
src/ws/client_g.html

@@ -9,6 +9,7 @@
 
 <body>
    <div id="table_div" style="height:600"></div>
+   <div id="chart_div"></div> 
    <button id="change-btn">change columns</button>
    <button id="test-btn">test</button>
   <form onsubmit="onSubmit(); return false;">
@@ -28,6 +29,19 @@
     var options = {allowHtml: true, sortColumn:1, 
     		showRowNumber: true, width: '100%', height: '100%'};
     
+    var chartOptions = {
+            width: 600,
+            height: 400,
+            legend: { position: 'top', maxLines: 3 },
+            bar: { groupWidth: '75%' },
+            isStacked: true,allowHtml: true,
+         /*series: {
+    			0:{color:'lightgreen'},
+    			1:{color:'black'},
+    			2:{color:'#1E90FF',},
+    			}*/ 
+    };
+    
 	google.load("visualization", "1.1", {packages:["corechart", 'table','gauge']});
 	   //google.setOnLoadCallback(drawTable);
 	google.setOnLoadCallback(init);

+ 1 - 1
src/ws/ws_server.py

@@ -199,7 +199,7 @@ class PortfolioTableModelListener(BaseMessageListener):
         try:
             logging.info("[%s] received %s from %s. content:[%d]" % (self.name, event, source, origin_request_id))
             self.mwss.get_server().send_message(self.mwss.clients[origin_request_id], 
-                                                json.dumps({'event': event, 'value': data_table_json})) 
+                                                json.dumps({'source': source, 'event': event, 'value': data_table_json})) 
         #except IndexError, KeyError:
         except:
             logging.error('[%s]. index error %d' % (event, origin_request_id))