04_股指ETF期权T型报价.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. # 股指ETF期权T型报价
  2. # 参考资料:
  3. # - 原始策略来源: https://www.joinquant.com/view/community/detail/a5a968ed72f2b827c051d337b0d74d04
  4. # - 研究网址: https://www.joinquant.com/research?target=research&url=/user/75474983526/notebooks/Options/%E8%82%A1%E6%8C%87ETF%E6%9C%9F%E6%9D%83T%E5%9E%8B%E6%8A%A5%E4%BB%B7.ipynb
  5. # TODO: 添加股指ETF期权T型报价相关代码
  6. import pandas as pd
  7. import numpy as np
  8. import talib as tb
  9. from pandas.plotting import table
  10. from jqdata import *
  11. #期权合约信息
  12. class OptionContract:
  13. preClose: 0 #前一天的收盘价
  14. marginUnit: 0 #单位保证金
  15. prePosition: 0 #前一天收盘的持仓量
  16. close: 0 #现价
  17. volume: 0 #成交量
  18. position: 0 #当前持仓量
  19. priceChangePct: 0 #收盘价涨跌幅
  20. positionChange: 0 #日增仓
  21. positionChangePct: 0 #日增仓比例
  22. rewardPct: 0 #报酬率(权利金/保证金)
  23. def __init__(self, preClose, marginUnit,
  24. prePosition, close, volume,
  25. position, priceChangePct,
  26. positionChange,
  27. positionChangePct,
  28. rewardPct):
  29. self.preClose = preClose
  30. self.marginUnit = marginUnit
  31. self.prePosition = prePosition
  32. self.close = close
  33. self.volume = volume
  34. self.position = position
  35. self.priceChangePct = priceChangePct
  36. self.positionChange = positionChange
  37. self.positionChangePct = positionChangePct
  38. self.rewardPct = rewardPct
  39. # 同一行权价的一组期权
  40. class OptionGroup:
  41. exercisePrice: 0 ##行权价
  42. call: None ##认购的类型
  43. put: None ##认沽的类型
  44. def __init__(self, exercisePrice, call, put):
  45. self.exercisePrice = exercisePrice
  46. self.call = call
  47. self.put = put
  48. def __init__(self, exercisePrice):
  49. self.exercisePrice = exercisePrice
  50. #数据实体
  51. CONTENT = [
  52. 'close',
  53. 'volume',
  54. 'position',
  55. 'priceChangePct',
  56. 'positionChange',
  57. 'positionChangePct',
  58. 'preClose',
  59. 'marginUnit',
  60. 'rewardPct'
  61. ]
  62. ##目前支持的域及对应的抬头
  63. CONTENT_HEADER_MAP = {
  64. 'rewardPct': '报酬率', #计算方式:权利金/卖出一手所需的保证金*100
  65. 'marginUnit': '保证金', #开盘前一手该期权的保证金额,没有随盘中价格变化更新
  66. 'preClose': '昨收',
  67. 'prePosition': '昨日持仓',
  68. 'close': '现价',
  69. 'volume': '成交量',
  70. 'position': '持仓量',
  71. 'priceChangePct': '涨跌幅',
  72. 'positionChange': '日增仓',
  73. 'positionChangePct': '日增仓率',
  74. }
  75. ##期权合约,以50ETF为例
  76. SUBJECT_MATTER = '510050.XSHG'
  77. ##期权合约,以300ETF为例
  78. #SUBJECT_MATTER = '510300.XSHG'
  79. ##查询数据日期,以2024-03-22为例
  80. DATA_DATE = '2024-03-22'
  81. #合约到期日,以50ETF2403为例
  82. EXPIRE_MONTH = '2024-03-27'
  83. #查询相关的合约
  84. qy = query(opt.OPT_CONTRACT_INFO).filter(
  85. opt.OPT_CONTRACT_INFO.underlying_symbol == SUBJECT_MATTER, ##期权标的物
  86. opt.OPT_CONTRACT_INFO.exercise_date == EXPIRE_MONTH,##期权到期日
  87. ).order_by(opt.OPT_CONTRACT_INFO.exercise_price, opt.OPT_CONTRACT_INFO.contract_type)
  88. optList = opt.run_query(qy)
  89. print(optList)
  90. optionGroups = {}
  91. for index, row in optList.iterrows():
  92. code = row['code'] #key - 期权代码
  93. #查询具体合约的信息,商品需要去掉开盘前的静态信息
  94. optionDailyQuery = query(opt.OPT_DAILY_PREOPEN).filter(
  95. opt.OPT_DAILY_PREOPEN.code==code).order_by(
  96. opt.OPT_DAILY_PREOPEN.date.desc()).limit(1)
  97. dailyData = opt.run_query(optionDailyQuery)
  98. realTimeQuery = query(opt.OPT_DAILY_PRICE).filter(
  99. opt.OPT_DAILY_PRICE.code==code,
  100. opt.OPT_DAILY_PRICE.date==DATA_DATE).order_by(
  101. opt.OPT_DAILY_PRICE.date.desc()).limit(1)
  102. realTimeData = opt.run_query(realTimeQuery)
  103. #期权基本信息
  104. exercisePrice = row['exercise_price'] #行权价
  105. contractType = row['contract_type'] #合约类型。CO-认购期权,PO-认沽期权
  106. #盘前静态表查询
  107. preClose = dailyData.loc[0].at['pre_close'] #前一天的收盘价
  108. marginUnit = int(dailyData.loc[0].at['margin_unit']) #单位保证金
  109. prePosition = dailyData.loc[0].at['position'] #前一天收盘的持仓量
  110. #实时表查询
  111. close = realTimeData.loc[0].at['close'] #现价
  112. volume = int(realTimeData.loc[0].at['volume']) #成交量
  113. position = realTimeData.loc[0].at['position'] #当前持仓量
  114. priceChangePct = str(round(realTimeData.loc[0].at['change_pct_close'], 2)) + '%' #收盘价涨跌幅
  115. #计算
  116. positionChange = position - prePosition #日增仓
  117. positionChangePct = str(round(abs(positionChange / prePosition * 100), 2)) + '%' #日增仓比例
  118. rewardPct = round(close * 10000 / marginUnit * 100, 2) #报酬率(权利金/保证金)
  119. #去除非标准的带A合约
  120. if(exercisePrice * 10000 % 500 != 0):
  121. continue
  122. optionContract = OptionContract(preClose, marginUnit,
  123. prePosition, close,
  124. volume, position,
  125. priceChangePct, positionChange,
  126. positionChangePct, rewardPct)
  127. if(exercisePrice in optionGroups):
  128. if(contractType == 'CO'):
  129. optionGroups[exercisePrice].call = optionContract
  130. else:
  131. optionGroups[exercisePrice].put = optionContract
  132. else:
  133. optionGroup = OptionGroup(exercisePrice)
  134. if(contractType == 'CO'):
  135. optionGroup.call = optionContract
  136. else:
  137. optionGroup.put = optionContract
  138. optionGroups[exercisePrice] = optionGroup
  139. list = optionGroups.values()
  140. rtitle = CONTENT.copy()
  141. rtitle.reverse()
  142. data = {}
  143. for key in rtitle:
  144. data['C-'+CONTENT_HEADER_MAP[key]] = []
  145. data['行权价'] = []
  146. for key in CONTENT:
  147. data['P-'+CONTENT_HEADER_MAP[key]] = []
  148. for option in list:
  149. for key in CONTENT:
  150. data['C-'+CONTENT_HEADER_MAP[key]].append(getattr(option.call, key))
  151. data['行权价'].append(option.exercisePrice)
  152. for key in rtitle:
  153. data['P-'+CONTENT_HEADER_MAP[key]].append(getattr(option.put, key))
  154. df = pd.DataFrame(data)
  155. df