portfolio_column_chart.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. # -*- coding: utf-8 -*-
  2. import sys, traceback, logging
  3. from rethink.portfolio_item import PortfolioRules, PortfolioItem, Portfolio
  4. import numpy as np
  5. from rethink.table_model import AbstractPortfolioTableModelListener, AbstractTableModel
  6. from ib.ext.Contract import Contract
  7. class PortfolioColumnChart():
  8. '''
  9. code to handle portfolio column chart
  10. [[ 0. 0. 0. -2. 0. ]
  11. [ 0. 0. 0. -1. 0. ]
  12. [ 0. 0. 0. 0. 0. ]
  13. [ 0. 0. 0. -3. 0. ]
  14. [ 0. 0. 0. 1. 0. ]
  15. [ 0. 0. 0. -4. 0. ]
  16. [ 0. 0. 0. 1. 0. ]
  17. [ 0. -2. 0. 1. 0. ]
  18. [ 0. -2. 1. 0. 0. ]
  19. [ 0. 0. 0. 0. 2.6]
  20. [-3. 0. 0. 0. 0. ]
  21. [ 0. 0. 0. 0. 0. ]
  22. [-1. 0. 0. 0. 0. ]
  23. [ 0. 0. -3. 0. 0. ]
  24. [ 0. 0. -1. 0. 0. ]]
  25. '''
  26. def __init__(self, pf):
  27. self.pf = pf
  28. self.xy_arr = None
  29. self.col_header = {'y_map': None, 'y_map_reverse': None}
  30. self.row_header = {'x_map': None, 'x_map_reverse': None}
  31. def get_object_name(self):
  32. return 'p-%s' % (id(self))
  33. def ckey_to_row(self, contract_key):
  34. p_item= self.pf.is_contract_in_portfolio(contract_key)
  35. if p_item:
  36. if p_item.get_instrument_type() == 'OPT':
  37. row = self.row_header['x_map'][p_item.get_strike()]
  38. return row
  39. else: #FUT average price
  40. col = self.col_header['y_map'][self.make_col_header(p_item)]
  41. for i in self.xy_arr.shape[0]:
  42. if self.xy_arr[i][col] <> 0:
  43. return i
  44. def get_values_at(self, row):
  45. rf = [{'v': self.row_header['x_map_reverse'][row]}]
  46. for rv in self.xy_arr[row]:
  47. rf.append({'v': rv})
  48. return rf
  49. def make_col_header(self, p_item):
  50. return '%s-%s-%s-%s' % (p_item.get_expiry(), p_item.get_symbol_id(),
  51. p_item.get_instrument_type(), p_item.get_right() )
  52. def get_JSON(self):
  53. p2_items = self.pf.get_portfolio_port_items().values()
  54. p1_items = filter(lambda x: x.get_symbol_id() in PortfolioRules.rule_map['interested_position_types']['symbol'], p2_items)
  55. p_items = filter(lambda x: x.get_instrument_type() in PortfolioRules.rule_map['interested_position_types']['instrument_type'], p1_items)
  56. print ','.join(str(x.get_strike()) for x in p_items)
  57. # row values domain
  58. # find out the strikes of all contracts purchased, for futures, use the average cost
  59. x_range = set(
  60. map(lambda x:int(round(x.get_strike(),-1)), filter(lambda x: x.get_instrument_type() in 'OPT', p_items)) +
  61. map(lambda x:int(round(x.get_port_field(PortfolioItem.AVERAGE_PRICE),-1)), filter(lambda x: x.get_instrument_type() in 'FUT', p_items))
  62. )
  63. # column values domain (month,symbol,contract_type, right)
  64. y_range = set(map(self.make_col_header, p_items))
  65. # sort the list then create a map that stores kv pairs of value:index_pos
  66. x_range = sorted(list(x_range))
  67. print x_range
  68. x_map = {}
  69. x_map_reverse = {}
  70. for i in range(len(x_range)):
  71. x_map[x_range[i]] = i
  72. x_map_reverse[i] = x_range[i]
  73. print '---xmap and xmap reverse'
  74. print x_map
  75. print x_map_reverse
  76. print '----'
  77. self.row_header['x_map'] = x_map
  78. self.row_header['x_map_reverse'] = x_map_reverse
  79. y_range = sorted(list(y_range))
  80. y_map = {}
  81. y_map_reverse = {}
  82. for i in range(len(y_range)):
  83. y_map[y_range[i]] = i
  84. y_map_reverse[i]= y_range[i]
  85. print '---ymap and ymap reverse'
  86. print y_map
  87. print y_map_reverse
  88. print '----'
  89. self.col_header['y_map'] = y_map
  90. self.col_header['y_map_reverse'] = y_map_reverse
  91. def set_ij(p_item):
  92. if p_item.get_instrument_type() == 'FUT':
  93. i = x_map[int(round(p_item.get_port_field(PortfolioItem.AVERAGE_PRICE), -1))]
  94. #
  95. # hard code logic below to convert number of MHI in HSI unit (that is 5:1)
  96. v = p_item.get_quantity() *\
  97. (PortfolioRules.rule_map['option_structure'][p_item.get_symbol_id()]['multiplier'] /
  98. PortfolioRules.rule_map['option_structure']['HSI']['multiplier']
  99. )
  100. else:
  101. i = x_map[int(round(p_item.get_strike(), -1))]
  102. v = p_item.get_quantity()
  103. j = y_map[self.make_col_header(p_item)]
  104. return (i,j,v)
  105. ijv_dist = map(set_ij, p_items)
  106. print ijv_dist
  107. xy_arr = np.zeros((len(x_range), len(y_range)))
  108. def update_ijv(ijv):
  109. xy_arr[ijv[0], ijv[1]] = ijv[2]
  110. return 1
  111. map(update_ijv, ijv_dist)
  112. print xy_arr
  113. def gen_datatable():
  114. ccj = {'cols':[{'id': 'strike', 'label': 'strike', 'type': 'number'}], 'rows':[]}
  115. for j in range(len(y_map_reverse)):
  116. ccj['cols'].append({'id': y_map_reverse[j], 'label': y_map_reverse[j], 'type': 'number' })
  117. def row_item(i):
  118. for m in range(xy_arr.shape[1]):
  119. ccj['rows'][i]['c'].append({'v':xy_arr[i][m]})
  120. for i in range(len(x_map_reverse)):
  121. ccj['rows'].append({'c':[{'v':x_map_reverse[i]}]})
  122. row_item(i)
  123. return ccj
  124. return gen_datatable()
  125. class PortfolioColumnChartTM(PortfolioColumnChart, AbstractTableModel, AbstractPortfolioTableModelListener):
  126. def __init__(self, name, pf, kproducer):
  127. PortfolioColumnChart.__init__(self, pf)
  128. AbstractPortfolioTableModelListener.__init__(self, name)
  129. self.request_ids = {}
  130. self.kproducer = kproducer
  131. # def get_column_count(self):
  132. # raise NotImplementedException
  133. #
  134. # def get_row_count(self):
  135. # raise NotImplementedException
  136. #
  137. # def get_column_name(self, col):
  138. # raise NotImplementedException
  139. #
  140. # def get_column_id(self, col):
  141. # raise NotImplementedException
  142. #
  143. # def get_value_at(self, row, col):
  144. # raise NotImplementedException
  145. #
  146. # def get_values_at(self, row):
  147. # raise NotImplementedException
  148. #
  149. # def set_value_at(self, row, col, value):
  150. # raise NotImplementedException
  151. #
  152. # def insert_row(self, values):
  153. # raise NotImplementedException
  154. def event_tm_table_structure_changed(self, event, source, origin_request_id, account, data_table_json):
  155. logging.info("[PortfolioColumnChartTM:%s] received %s content:[%s]" % (self.name, event, vars()))
  156. def event_tm_request_table_structure(self, event, request_id, target_resource, account):
  157. self.request_ids[request_id] = {'request_id': request_id, 'account': account}
  158. logging.info("[PortfolioColumnChartTM:%s] received %s content:[%s]" % (self.name, event, vars()))