In [1]:
from bs4 import BeautifulSoup
import requests
from pandas import DataFrame
from yahoo_finance import Share

In [2]:
r = requests.get("https://www.hkex.com.hk/eng/prod/drprod/so/holidayex2.htm")
soup = BeautifulSoup(r.text, 'html.parser')
table = soup.find("table", { "class" : "ms-rteTable-2" })

d = {"contract" : [],
           "expiry" : []}

for row in table.findAll("tr")[1:]:
    cell = row.findAll("td")
    d['contract'].append(cell[0].find("p").contents[0])
    d['expiry'].append(cell[1].find("p").contents[0])
    
df = DataFrame.from_dict(d)
df


Out[2]:
contract expiry
0 Jan-15 29-Jan-15
1 Feb-15 26-Feb-15
2 Mar-15 30-Mar-15
3 Apr-15 29-Apr-15
4 May-15 28-May-15
5 Jun-15 29-Jun-15
6 Jul-15 30-Jul-15
7 Aug-15 28-Aug-15
8 Sep-15 29-Sep-15
9 Oct-15 29-Oct-15
10 Nov-15 27-Nov-15
11 Dec-15 30-Dec-15
12 Jan-16 28-Jan-16
13 Feb-16 26-Feb-16
14 Mar-16 30-Mar-16
15 Apr-16 28-Apr-16
16 May-16 30-May-16
17 Jun-16 29-Jun-16
18 Jul-16 28-Jul-16
19 Aug-16 30-Aug-16
20 Sep-16 29-Sep-16
21 Oct-16 28-Oct-16
22 Nov-16 29-Nov-16
23 Dec-16 29-Dec-16

In [5]:
#
#   bs4defectworkaround.py  --  workaround for BS4 bug #1430633
#
#   John Nagle
#   SiteTruth.com
#   March, 2014
#
#   License: public domain
#   No warranty.
#
#   The BeautifulSoup (BS4) tree builder, when used with HTML5lib,
#   produces trees in which the previous_element and next_element links
#   are wrong.  This occurs because HTML5lib sometimes adds children to
#   elements other than the previous element.  The parse tree as defined
#   by the "contents" element is correct, but the links used for faster
#   search through the tree, especially next_element, are wrong. This
#   can crash the "find" or "find_all" functions, because their termination
#   condition is delicate.
#
#   "fixbs4tree" goes through a BS4 parse tree recursively and checks or
#   fixes this problem.  It's a workaround, not a permanent fix.
#
#
def fixbs4tree(tree, repair=False) :
    """
    Check or repair BS4 tree links.  
    
    This is a workaround for bad next_element links created by the
    combination of bs4 and html5lib.  See BS4 Bug #1430633.
    
    Assumes "contents" links are correct; everything else is checked or fixed.
    
    If "repair" is True, bad links are fixed; otherwise RuntimeError is raised.
    """
    _fixbs4subtree(tree, None, None, repair)

def _fixbs4subtree(elt, parent, prevelt, repair) :
    """
    Recurse through tree in element order, checking or repairing links.
    """
    assert(elt.parent is parent)
    if repair :                                         # if repairing
        elt.previous_element = prevelt                  # REPAIR previous_element
    else :
        if not elt.previous_element is prevelt :        # if previous_element is wrong
            raise RuntimeError("BS4 parser internal error (Bug #1430633) - previous_element link in tree incorrect.")
    if prevelt :                                        # if there is a previous element
        if repair :                                     # if repairing
            prevelt.next_element = elt                  # REPAIR next_element
        else :                                          # otherwise check and report
            if not prevelt.next_element is elt :
                raise RuntimeError("BS4 parser internal error (Bug #1430633) - next_element link in tree incorrect.")               
    contents = getattr(elt,"contents", None)            # get contents or none 
    if contents :                                       # if has contents
        prevsib = None                                  # no previous sibling yet
        prevelt = elt
        for workelt in contents :                       # for all children
            #   Check sibling links. Those should be right.
            assert(workelt.previous_sibling is prevsib)
            if prevsib :
                assert(prevsib.next_sibling is workelt) 
            #   Check previous_element link.
            prevelt = _fixbs4subtree(workelt, elt, prevelt, repair) # recurse to fix
            prevsib = workelt
        return(prevelt)                                 # return last deepest child
    else :
        return(elt)                                     # no children

In [6]:
r = requests.get("https://www.hkex.com.hk/eng/prod/drprod/so/classlist_so.htm")
soup = BeautifulSoup(r.content.decode('utf-8', 'ignore'), 'html5lib')
fixbs4tree(soup, repair=True)
tables = soup.find("td", {"class":"hkex-maincontent-text"}).find_all("table")
#.find_all("table", {"class": "MsoNormalTable"})
d = {"num":[],
        "id":[],
        "underlying":[],
      "code":[],
       "contract_size":[],
       "lots":[],
        "tier":[],
        "limit":[],
        "taiwan":[]}
tables
for row in tables[0].findAll("tr", {"style": "height:12.75pt"})[1:]:
  cell = row.findAll("td")
  d['num'].append(cell[0].find("p").getText())
  d['id'].append(int(cell[1].find("p").getText()))
  d['underlying'].append(cell[2].getText().strip())
  d['code'].append(cell[3].find("p").getText())
  d['contract_size'].append(int(cell[4].find("p").getText().replace(",","")))
  d['lots'].append(int(cell[5].find("p").getText().replace(",","")))
  d['tier'].append(int(cell[6].find("p").getText().replace(",","")))
  d['limit'].append(int(cell[7].find("p").getText().replace(",","")))
  d['taiwan'].append(cell[8].getText().strip() != "")
for row in tables[1].findAll("tr", {"style": "height:12.75pt"})[1:]:
  cell = row.findAll("td")
  d['num'].append(cell[0].find("p").getText())
  d['id'].append(int(cell[1].find("p").getText()))
  d['underlying'].append(cell[2].getText().strip())
  d['code'].append(cell[3].find("p").getText())
  d['contract_size'].append(int(cell[4].find("p").getText().replace(",","")))
  d['lots'].append(1)
  d['tier'].append(int(cell[5].find("p").getText().replace(",","")))
  d['limit'].append(int(cell[6].find("p").getText().replace(",","")))
  d['taiwan'].append(cell[7].getText().strip() != "")
df = DataFrame.from_dict(d)
df

def get_option_params(n):
   return df[df['id'] == int(n)]

def option_info(i):
    yahoo_symbol = "%04d.HK" % i
    s = Share(yahoo_symbol)
    price = float(s.get_price())
    contract_size = get_option_params(int(i))['contract_size'].iloc[0]
    print ("Symbol:  %s" % yahoo_symbol)
    print("Contract size: %i" % contract_size)
    print("Price: %.2f" % price)
    print("Contract value %2f" % (price * contract_size))

In [5]:
df


Out[5]:
code contract_size id limit lots num taiwan tier underlying
0 XAB 10000 1288 50000 10 1 True 1 Agricultural Bank of China Limited
1 AIA 1000 1299 50000 5 2 True 1 AIA Group Limited
2 NCL 1000 1336 50000 10 3 False 1 New China Life Insurance Co. Ltd.
3 PIN 5000 1339 50000 5 4 False 2 The People's Insurance Company (Group) of Chin...
4 CDA 5000 1359 50000 5 5 False 2 China Cinda Asset Management Co., Ltd
5 MSB 2500 1988 50000 5 6 False 2 China Minsheng Banking Corporation Limited
6 CPI 1000 2601 50000 5 7 True 1 China Pacific Insurance (Group) Co., Ltd.
7 CSA 5000 2822 30000 25 8 False 1 CSOP FTSE China A50 ETF
8 A50 5000 2823 50000 50 9 True 1 iShares FTSE A50 China Index ETF#
9 CS3 1000 2827 30000 5 10 False 2 W.I.S.E. - CSI 300 China Tracker #
10 HCF 1000 2828 50000 5 11 False 1 Hang Seng H-Share Index ETF
11 AMC 2000 3188 30000 10 12 False 1 ChinaAMC CSI 300 Index ETF
12 PLE 5000 3800 50000 5 13 False 2 GCL-Poly Energy Holdings Ltd.
13 CTS 1000 6030 50000 2 14 False 1 CITIC Securities Co. Ltd.
14 HAI 2000 6837 50000 5 15 False 1 Haitong Securities Co., Ltd.
15 CKH 500 1 50000 1 1 False 1 CK Hutchison Holdings Ltd.
16 CLP 500 2 50000 1 2 False 1 CLP Holdings Limited
17 HKG 1000 3 50000 1 3 False 2 The Hong Kong and China Gas Company Limited
18 WHL 1000 4 50000 1 4 False 1 The Wharf (Holdings) Limited
19 HKB 400 5 50000 1 5 True 1 HSBC Holdings Plc.
20 HEH 500 6 50000 1 6 False 1 Power Assets Holdings Limited
21 HSB 100 11 50000 1 7 False 2 Hang Seng Bank Limited
22 HLD 1000 12 50000 1 8 False 1 Henderson Land Development Company Limited
23 SHK 1000 16 50000 1 9 True 1 Sun Hung Kai Properties Limited
24 NWD 1000 17 50000 1 10 True 3 New World Development Company Limited
25 SWA 500 19 50000 1 11 True 1 Swire Pacific Limited
26 BEA 200 23 50000 1 12 False 3 The Bank of East Asia, Limited
27 GLX 1000 27 50000 1 13 True 1 Galaxy Entertainment Group Limited
28 MTR 500 66 50000 1 14 False 2 MTR Corporation Limited
29 KLE 2000 135 50000 1 15 False 1 Kunlun Energy Co. Ltd.
... ... ... ... ... ... ... ... ... ...
51 CTB 1000 998 50000 1 37 False 3 China CITIC Bank Corporation Limited
52 HGN 500 1044 30000 1 38 False 1 Hengan International Group Co. Ltd.
53 CSE 500 1088 50000 1 39 True 2 China Shenhua Energy Company Limited
54 CRL 2000 1109 50000 1 40 False 1 China Resources Land Ltd.
55 YZC 2000 1171 50000 1 41 True 2 Yanzhou Coal Mining Company Limited
56 CRC 500 1186 50000 1 42 False 3 China Railway Construction Corporation Limited
57 BYD 500 1211 50000 1 43 False 1 BYD Company Limited
58 XIC 1000 1398 50000 1 44 True 3 Industrial and Commercial Bank of China Limited
59 CCC 1000 1800 50000 1 45 True 3 China Communications Construction Company Limited
60 BIH 1000 1880 50000 1 46 True 3 Belle International Holdings Limited
61 CCE 1000 1898 50000 1 47 True 3 China Coal Energy Company Limited
62 CCS 500 1919 50000 1 48 False 3 China COSCO Holdings Company Limited
63 SAN 400 1928 50000 1 49 True 2 Sands China Ltd.
64 FIH 1000 2038 50000 1 50 False 3 FIH Mobile Limited
65 MGM 400 2282 50000 1 51 False 2 MGM China Holdings Limited
66 PAI 500 2318 50000 1 52 True 1 Ping An Insurance (Group) Company of China, Ltd.
67 MEN 1000 2319 50000 1 53 False 1 China Mengniu Dairy Co. Ltd.
68 PIC 2000 2328 50000 1 54 False 1 PICC Property and Casualty Company Limited
69 GWM 500 2333 50000 1 55 False 3 Great Wall Motor Co. Limited ^
70 BOC 500 2388 50000 1 56 True 2 BOC Hong Kong (Holdings) Limited
71 ALC 2000 2600 50000 1 57 False 3 Aluminum Corporation of China Limited
72 CLI 1000 2628 50000 1 58 True 2 China Life Insurance Company Limited
73 RFP 400 2777 50000 1 59 False 3 Guangzhou R&F Properties Co., Ltd.
74 TRF 500 2800 50000 1 60 False 2 Tracker Fund of Hong Kong
75 STC 50 2888 50000 1 61 False 3 Standard Chartered PLC
76 ZJM 2000 2899 50000 1 62 False 3 Zijin Mining Group Company Limited
77 NBM 2000 3323 50000 1 63 True 2 China National Building Material Company Limited
78 BCM 1000 3328 50000 1 64 True 3 Bank of Communications Co., Ltd.
79 KSO 1000 3888 50000 1 65 False 2 Kingsoft Corporation Ltd.
80 CMB 500 3968 50000 1 66 False 3 China Merchants Bank Co., Ltd.

81 rows × 9 columns


In [6]:
get_option_params(2800)


Out[6]:
code contract_size id limit lots num taiwan tier underlying
74 TRF 500 2800 50000 1 60 False 2 Tracker Fund of Hong Kong

In [8]:
r = requests.get("http://www.hkex.com.hk/eng/stat/dmstat/dayrpt/dqe150813.htm")

In [9]:
op = get_option_params(388)

In [10]:
s  = Share('0388.HK')
float(s.get_price())


Out[10]:
182.0

In [34]:
op['contract_size'].iloc[0]  * float(s.get_price())


Out[34]:
17830.0

In [42]:


In [7]:
option_info(2800)


Symbol:  2800.HK
Contract size: 500
Price: 21.60
Contract value 10800.000000

In [9]:
option_info(3888)


Symbol:  3888.HK
Contract size: 1000
Price: 15.10
Contract value 15100.000000

In [10]:
option_info(388)


Symbol:  0388.HK
Contract size: 100
Price: 176.80
Contract value 17680.000000

In [8]:
option_info(27)


Symbol:  0027.HK
Contract size: 1000
Price: 27.10
Contract value 27100.000000

In [ ]: