sample_tws_client.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. # -*- coding: utf-8 -*-
  2. import sys, traceback
  3. import json
  4. import logging
  5. import thread, threading
  6. from threading import Lock
  7. import ConfigParser
  8. from time import sleep
  9. import time, datetime
  10. from ib.ext.Contract import Contract
  11. from ib.ext.Order import Order
  12. from ib.ext.ExecutionFilter import ExecutionFilter
  13. from random import randint
  14. from finopt.options_analytics import AnalyticsListener
  15. from misc2.helpers import ContractHelper, OrderHelper, ExecutionFilterHelper
  16. from finopt.options_chain import OptionsChain
  17. from comms.tws_client import SimpleTWSClient
  18. from kafka import KafkaConsumer
  19. from comms.tws_protocol_helper import TWS_Protocol
  20. class SampleClient(SimpleTWSClient):
  21. tickerMap = {}
  22. def dump(self, msg_name, mapping):
  23. # the mapping is a comms.tws_protocol_helper.Message object
  24. # which can be accessed directly using the __dict__.['xxx'] method
  25. items = list(mapping.items())
  26. items.sort()
  27. print ('>>> %s <<< %s' % (msg_name, ''.join('%s=%s, '% (k, v if k <> 'ts' else datetime.datetime.fromtimestamp(v).strftime('%Y-%m-%d %H:%M:%S.%f')) for k, v in items)))
  28. def accountSummaryEnd(self, items):
  29. self.dump('accountSummaryEnd', items)
  30. def accountSummary(self, items):
  31. self.dump('accountSummary', items)
  32. # override the tickSize message
  33. def tickSize(self, items):
  34. try:
  35. contract = self.tickerMap[items.__dict__['tickerId']]
  36. field = items.__dict__['field']
  37. ct = ContractHelper.kv2object(contract, Contract)
  38. print 'tickSize>> %s' % ('[%d:%s] %s=%0.4f [%s]' % \
  39. (items.__dict__['tickerId'], ContractHelper.makeRedisKeyEx(ct),\
  40. 'bid' if field == 0 else ('ask' if field == 3 else ('last' if field == 5 else field)), \
  41. items.__dict__['size'], datetime.datetime.fromtimestamp(items.__dict__['ts']).strftime('%Y-%m-%d %H:%M:%S.%f')))
  42. except KeyError:
  43. print 'tickSize: keyerror: (this could happen on the 1st run as the subscription manager sub list is still empty.'
  44. print items
  45. def tickPrice(self, items):
  46. try:
  47. contract = self.tickerMap[items.__dict__['tickerId']]
  48. field = items.__dict__['field']
  49. ct = ContractHelper.kv2object(contract, Contract)
  50. print 'tickPrice>> %s' % ('[%d:%s] %s=%0.4f [%s]' % \
  51. (items.__dict__['tickerId'], ContractHelper.makeRedisKeyEx(ct),\
  52. 'bid_q' if field == 1 else ('ask_q' if field == 2 else ('last_q' if field == 4 else field)), \
  53. items.__dict__['price'], datetime.datetime.fromtimestamp(items.__dict__['ts']).strftime('%Y-%m-%d %H:%M:%S.%f')))
  54. except KeyError:
  55. print 'tickPrice: keyerror:'
  56. print items
  57. def tickString(self, items):
  58. pass
  59. def tickGeneric(self, items):
  60. pass
  61. def positionEnd(self, items):
  62. self.dump('positionEnd', items)
  63. def position(self, items):
  64. self.dump('position', items)
  65. #pass
  66. def error(self, items):
  67. self.dump('error', items)
  68. def error_0(self, items):
  69. self.dump('error', items)
  70. def error_1(self, items):
  71. self.dump('error', items)
  72. def gw_subscriptions(self, items):
  73. # <class 'comms.tws_protocol_helper.Message'>
  74. # sample
  75. #[[0, u'{"m_conId": 0, "m_right": "", "m_symbol": "HSI", "m_secType": "FUT", "m_includeExpired": false, "m_expiry": "20151127", "m_currency": "HKD", "m_exchange": "HKFE", "m_strike": 0}'], [1, u'{"m_conId": 0, "m_right": "P", "m_symbol": "HSI", "m_secType": "OPT", "m_includeExpired": false, "m_expiry": "20151127", "m_currency": "HKD", "m_exchange": "HKFE", "m_strike": 22200}'], [2, u'{"m_conId": 0, "m_right": "P", "m_symbol": "HSI", "m_secType": "OPT", "m_includeExpired": false, "m_expiry": "20151127", "m_currency": "HKD", "m_exchange": "HKFE", "m_strike": 22400}'], [3, u'{"m_conId": 0, "m_right": "P", "m_symbol": "HSI", "m_secType": "OPT", "m_includeExpired": false, "m_expiry": "20151127", "m_currency": "HKD", "m_exchange": "HKFE", "m_strike": 22600}'], [4, u'{"m_conId": 0, "m_right": "P", "m_symbol": "HSI", "m_secType": "OPT", "m_includeExpired": false, "m_expiry": "20151127", "m_currency": "HKD", "m_exchange": "HKFE", "m_strike": 22800}'], [5, u'{"m_conId": 0, "m_right": "P", "m_symbol": "HSI", "m_secType": "OPT", "m_includeExpired": false, "m_expiry": "20151127", "m_currency": "HKD", "m_exchange": "HKFE", "m_strike": 23000}'], [6, u'{"m_conId": 0, "m_right": "P", "m_symbol": "HSI", "m_secType": "OPT", "m_includeExpired": false, "m_expiry": "20151127", "m_currency": "HKD", "m_exchange": "HKFE", "m_strike": 23200}']]
  76. #print items.__dict__['subscriptions']
  77. #l = map(lambda x: {x[0]: x[1]}, map(lambda x: (x[0], ContractHelper.kvstring2object(x[1], Contract)), items.__dict__['subscriptions']))
  78. l = map(lambda x: {x[0]: x[1]}, map(lambda x: (x[0], json.loads(x[1])), items.__dict__['subscriptions']))
  79. for i in l:
  80. self.tickerMap.update(i)
  81. print 'gw_subscriptions -> dump tickerMap '
  82. print self.tickerMap
  83. def gw_subscription_changed(self, items):
  84. print '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[['
  85. print items
  86. # override this function to perform your own processing
  87. # def accountDownloadEnd(self, items):
  88. # pass
  89. # override this function to perform your own processing
  90. # def execDetailsEnd(self, items):
  91. # pass
  92. # override this function to perform your own processing
  93. # def updateAccountTime(self, items):
  94. # pass
  95. # override this function to perform your own processing
  96. # def deltaNeutralValidation(self, items):
  97. # pass
  98. # override this function to perform your own processing
  99. # def orderStatus(self, items):
  100. # pass
  101. # override this function to perform your own processing
  102. # def updateAccountValue(self, items):
  103. # pass
  104. # override this function to perform your own processing
  105. # def historicalData(self, items):
  106. # pass
  107. # override this function to perform your own processing
  108. # def openOrderEnd(self, items):
  109. # pass
  110. # override this function to perform your own processing
  111. # def updatePortfolio(self, items):
  112. # pass
  113. # override this function to perform your own processing
  114. # def managedAccounts(self, items):
  115. # pass
  116. # override this function to perform your own processing
  117. # def contractDetailsEnd(self, items):
  118. # pass
  119. # override this function to perform your own processing
  120. # def positionEnd(self, items):
  121. # pass
  122. # override this function to perform your own processing
  123. # def bondContractDetails(self, items):
  124. # pass
  125. # override this function to perform your own processing
  126. # def accountSummary(self, items):
  127. # pass
  128. # override this function to perform your own processing
  129. # def updateNewsBulletin(self, items):
  130. # pass
  131. # override this function to perform your own processing
  132. # def scannerParameters(self, items):
  133. # pass
  134. # override this function to perform your own processing
  135. # def tickString(self, items):
  136. # pass
  137. # override this function to perform your own processing
  138. # def accountSummaryEnd(self, items):
  139. # pass
  140. # override this function to perform your own processing
  141. # def scannerDataEnd(self, items):
  142. # pass
  143. # override this function to perform your own processing
  144. # def commissionReport(self, items):
  145. # pass
  146. # override this function to perform your own processing
  147. # def error(self, items):
  148. # pass
  149. # override this function to perform your own processing
  150. # def tickGeneric(self, items):
  151. # pass
  152. # override this function to perform your own processing
  153. # def tickPrice(self, items):
  154. # pass
  155. # override this function to perform your own processing
  156. # def nextValidId(self, items):
  157. # pass
  158. # override this function to perform your own processing
  159. # def openOrder(self, items):
  160. # pass
  161. # override this function to perform your own processing
  162. # def realtimeBar(self, items):
  163. # pass
  164. # override this function to perform your own processing
  165. # def contractDetails(self, items):
  166. # pass
  167. # override this function to perform your own processing
  168. # def execDetails(self, items):
  169. # pass
  170. # override this function to perform your own processing
  171. # def tickOptionComputation(self, items):
  172. # pass
  173. # override this function to perform your own processing
  174. # def updateMktDepth(self, items):
  175. # pass
  176. # override this function to perform your own processing
  177. # def scannerData(self, items):
  178. # pass
  179. # override this function to perform your own processing
  180. # def currentTime(self, items):
  181. # pass
  182. # override this function to perform your own processing
  183. # def error_0(self, items):
  184. # pass
  185. # override this function to perform your own processing
  186. # def error_1(self, items):
  187. # pass
  188. # override this function to perform your own processing
  189. # def tickSnapshotEnd(self, items):
  190. # pass
  191. # override this function to perform your own processing
  192. # def tickSize(self, items):
  193. # pass
  194. # override this function to perform your own processing
  195. # def receiveFA(self, items):
  196. # pass
  197. # override this function to perform your own processing
  198. # def connectionClosed(self, items):
  199. # pass
  200. # override this function to perform your own processing
  201. # def position(self, items):
  202. # pass
  203. # override this function to perform your own processing
  204. # def updateMktDepthL2(self, items):
  205. # pass
  206. # override this function to perform your own processing
  207. # def fundamentalData(self, items):
  208. # pass
  209. # override this function to perform your own processing
  210. # def tickEFP(self, items):
  211. # pass
  212. def on_ib_message(msg):
  213. print msg
  214. def makeOrder(action, orderID, tif, orderType, price, qty):
  215. newOptOrder = Order()
  216. newOptOrder.m_orderId = orderID
  217. newOptOrder.m_clientId = 0
  218. newOptOrder.m_permid = 0
  219. newOptOrder.m_action = action
  220. newOptOrder.m_lmtPrice = price
  221. newOptOrder.m_auxPrice = 0
  222. newOptOrder.m_tif = tif
  223. newOptOrder.m_transmit = True
  224. newOptOrder.m_orderType = orderType
  225. newOptOrder.m_totalQuantity = qty
  226. return newOptOrder
  227. def test1():
  228. twsc = SimpleTWSClient(host, port, '888')
  229. twsc.registerAll([on_ib_message])
  230. #twsc.get_command_handler().reqAccountSummary(100, 'All', "AccountType,NetLiquidation,TotalCashValue,BuyingPower,EquityWithLoanValue")
  231. contract = Contract() #
  232. contract.m_symbol = 'WMT'
  233. contract.m_currency = 'USD'
  234. contract.m_secType = 'STK'
  235. contract.m_exchange = 'SMART'
  236. twsc.get_command_handler().reqMktData(contract)
  237. twsc.connect()
  238. sleep(4)
  239. twsc.disconnect()
  240. print 'completed...'
  241. def test15():
  242. contract = Contract() #
  243. contract.m_symbol = 'WMT'
  244. contract.m_currency = 'USD'
  245. contract.m_secType = 'STK'
  246. contract.m_exchange = 'SMART'
  247. c = SampleClient(host, port, 'SampleClient-777')
  248. c.connect()
  249. c.get_command_handler().reqMktData(contract)
  250. sleep(4)
  251. c.disconnect()
  252. print 'completed...'
  253. def test2():
  254. contract = Contract() #
  255. contract.m_symbol = 'EUR'
  256. contract.m_currency = 'USD'
  257. contract.m_secType = 'CASH'
  258. contract.m_exchange = 'IDEALPRO'
  259. c = SampleClient(host, port, 'SampleClient-777')
  260. c.connect()
  261. c.get_command_handler().gw_req_subscriptions()
  262. #c.get_command_handler().reqIds()
  263. c.get_command_handler().reqMktData(contract)
  264. for i in range(567,568):
  265. orderID = i
  266. order = makeOrder( 'SELL', i, 'DAY', 'LMT', 1.0, randint(10,20) * 1000)
  267. c.get_command_handler().placeOrder(orderID, contract, order)
  268. sleep(3)
  269. c.get_command_handler().reqOpenOrders()
  270. c.get_command_handler().reqExecutions()
  271. c.get_command_handler().reqPositions()
  272. sleep(8)
  273. c.disconnect()
  274. print 'completed...'
  275. def test3():
  276. c = SampleClient(host, port, 'SampleClient-777')
  277. c.connect()
  278. # m_clientId = 0 # zero means no filtering on this field
  279. # m_acctCode = ""
  280. # m_time = ""
  281. # m_symbol = ""
  282. # m_secType = ""
  283. # m_exchange = ""
  284. # m_side = ""
  285. filter = ExecutionFilterHelper.kv2object({'m_time': '20151104 09:35:00'}, ExecutionFilter)
  286. c.get_command_handler().reqExecutions(filter)
  287. sleep(7)
  288. #"yyyymmdd-hh:mm:ss"
  289. c.disconnect()
  290. def test4():
  291. #global host, port
  292. f = open('/home/larry/l1304/workspace/finopt/data/subscription-nov-HSI.txt')
  293. lns = f.readlines()
  294. cs = map (lambda l: ContractHelper.makeContract(tuple(l.strip('\n').split(','))), lns)
  295. c = SampleClient(host, port, 'SampleClient-777')
  296. c.connect()
  297. #for contract in cs:
  298. #c.get_command_handler().reqMktData(cs[0])
  299. #
  300. # contract = Contract() #
  301. # contract.m_symbol = 'EUR'
  302. # contract.m_currency = 'USD'
  303. # contract.m_secType = 'CASH'
  304. # contract.m_exchange = 'IDEALPRO'
  305. # c.get_command_handler().reqMktData(contract)
  306. #
  307. # contract.m_symbol = 'HSI'
  308. # contract.m_currency = 'HKD'
  309. # contract.m_secType = 'OPT'
  310. # contract.m_exchange = 'HKFE'
  311. # contract.m_strike = 21000
  312. # contract.m_multiplier = 50.0
  313. # contract.m_includeExpired = False
  314. #
  315. # contract.m_right = 'P'
  316. # contract.m_expiry = '20151127'
  317. contract = Contract()
  318. contract.m_symbol = 'GOOG'
  319. contract.m_currency = 'USD'
  320. contract.m_secType = 'STK'
  321. contract.m_exchange = 'SMART'
  322. #contract.m_strike = 58.5
  323. #contract.m_multiplier = 100
  324. #contract.m_includeExpired = False
  325. #contract.m_right = 'P'
  326. #contract.m_expiry = '20151120'
  327. c.get_command_handler().reqMktData(contract)
  328. contract = Contract()
  329. contract.m_symbol = 'EWT'
  330. contract.m_currency = 'USD'
  331. contract.m_secType = 'STK'
  332. contract.m_exchange = 'SMART'
  333. c.get_command_handler().reqMktData(contract)
  334. sleep(1)
  335. c.get_command_handler().gw_req_subscriptions()
  336. sleep(10)
  337. c.disconnect()
  338. def test5():
  339. print '******************************** TEST 5'
  340. c = SampleClient(host, port, 'SampleClient-777')
  341. c.connect()
  342. #c.get_command_handler().reqIds()
  343. c.get_command_handler().gw_req_subscriptions()
  344. c.get_command_handler().reqExecutions()
  345. sleep(8)
  346. c.disconnect()
  347. def test6():
  348. contractTuple = ('HSI', 'FUT', 'HKFE', 'HKD', '20151127', 0, '')
  349. #contractTuple = ('VMW', 'STK', 'SMART', 'USD', '', 0, '')
  350. contract = ContractHelper.makeContract(contractTuple)
  351. oc = OptionsChain('test6')
  352. oc.set_underlying(contract)
  353. oc.set_option_structure(contract, 200, 50, 0.005, 0.003, '20151127')
  354. oc.build_chain(22300, 0.1)
  355. c = SampleClient(host, port, 'SampleClient-777')
  356. c.connect()
  357. #c.get_command_handler().reqIds()
  358. c.get_command_handler().gw_req_subscriptions()
  359. c.get_command_handler().reqMktData(contract)
  360. for ct in oc.get_option_chain():
  361. c.get_command_handler().reqMktData(ct.get_contract())
  362. print ContractHelper.object2kvstring(ct.get_contract())
  363. sleep(8)
  364. c.disconnect()
  365. def test7():
  366. contractTuple = ('QQQ', 'STK', 'SMART', 'USD', '', 0, '')
  367. contract = ContractHelper.makeContract(contractTuple)
  368. oc = OptionsChain('t7')
  369. oc.set_underlying(contract)
  370. # underlying, spd_size, multiplier, rate, div, expiry):
  371. oc.set_option_structure(contract, 0.5, 100, 0.0012, 0.0328, '20170217')
  372. oc.build_chain(125, 0.04, 0.22)
  373. c = SampleClient(host, port, 'SampleClient-777')
  374. c.connect()
  375. #c.get_command_handler().reqIds()
  376. c.get_command_handler().gw_req_subscriptions()
  377. c.get_command_handler().reqMktData(contract)
  378. for ct in oc.get_option_chain():
  379. c.get_command_handler().reqMktData(ct.get_contract())
  380. print ContractHelper.object2kvstring(ct.get_contract())
  381. sleep(1)
  382. c.disconnect()
  383. def test8():
  384. # c = SampleClient(host, port, 'SampleClient-777')
  385. # c.connect()
  386. consumer = KafkaConsumer( *[(v,0) for v in list(TWS_Protocol.oceEvents)] , \
  387. metadata_broker_list=['%s:%s' % (host, port)],\
  388. client_id = 'test8',\
  389. group_id = 'epc.group',\
  390. auto_commit_enable=True,\
  391. consumer_timeout_ms = 2000,\
  392. auto_commit_interval_ms=30 * 1000,\
  393. auto_offset_reset='smallest')
  394. # c.get_command_handler().gw_req_subscriptions()
  395. for message in consumer:
  396. print ("received %s:%d:%d: key=%s value=%s" % (message.topic, message.partition,
  397. message.offset, message.key,
  398. message.value))
  399. print 'here'
  400. # c.disconnect()
  401. def on_analytics(msg):
  402. print msg
  403. kv = json.loads(msg)
  404. print 'x=%s imvol=%0.2f theta=%0.2f' % (kv['contract']['m_strike'], kv['analytics']['imvol'],kv['analytics']['theta'])
  405. def test9():
  406. al = AnalyticsListener(host, port, 'al')
  407. al.registerAll([on_analytics])
  408. al.start()
  409. if __name__ == '__main__':
  410. """
  411. this sample demonstrates how to use SimpleTWSClient
  412. to connect to IB TWS gateway
  413. usage scenarios:
  414. case 1
  415. re-use SimpleTWSClient object
  416. register to listen for all messages
  417. perform processing within the callback function
  418. case 2
  419. inherit SimpleTWSClient class
  420. override event callback functions to use
  421. each function associates with a specific message type
  422. """
  423. if len(sys.argv) != 2:
  424. print("Usage: %s <test case #>" % sys.argv[0])
  425. exit(-1)
  426. choice= sys.argv[1]
  427. logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s',
  428. filename= '/home/larry-13.04/workspace/finopt/log/unitest.log')
  429. # bootstrap server settings
  430. host = 'localhost'
  431. port = 9092
  432. print 'choice: %s' % choice
  433. test4()
  434. #test8()
  435. # if choice == '2':
  436. #
  437. # test2()
  438. # else:
  439. #
  440. # test3()