2017年5月31日 星期三
2017年5月22日 星期一
Google's Undocumented Finance API
這幾天來因yahoo finance的歷史股價下載api中斷,我便決心轉用google finance。
原本很簡單的,google finance的網頁有過往股價的顯示和下載如:
https://www.google.com.hk/finance/historical?q=HKG:2800&startdate=2012-01-01&enddate=2017-12-31&num=200&output=csv
但... :( 竟然得到以下對待!:-
404. That’s an error.
The requested URL was not found on this server. That’s all we know.
原來非美國股票只能顯示(&output=),不能下載(&output=csv)。
我參考了 http://www.networkerror.org/component/content/article/1-technical-wootness/44-googles-undocumented-finance-api.html
動手做了以下的 ods oobasic 代碼 (excel vba 請斟酌改動):
原本很簡單的,google finance的網頁有過往股價的顯示和下載如:
https://www.google.com.hk/finance/historical?q=HKG:2800&startdate=2012-01-01&enddate=2017-12-31&num=200&output=csv
但... :( 竟然得到以下對待!:-
404. That’s an error.
The requested URL was not found on this server. That’s all we know.
原來非美國股票只能顯示(&output=),不能下載(&output=csv)。
我參考了 http://www.networkerror.org/component/content/article/1-technical-wootness/44-googles-undocumented-finance-api.html
動手做了以下的 ods oobasic 代碼 (excel vba 請斟酌改動):
-------------------------------------------------------
'20170520 - try google instead of yahoo
' cURL = "http://ichart.finance.yahoo.com/table.csv?s=" & cSymbols & "&a=" & cStartMonth & "&b=" & cStartDay & "&c=" & cStartYear & "&d=" & cEndMonth & "&e=" & cEndDay & "&f=" & cEndYear & "&g=" & cGranularity & "&ignore=.csv"
cURL = "https://www.google.com/finance/getprices?q=" & LEFT(cSymbols,4) & "&x=HKG&i=86400&p=5Y&f=d,c,h,l,o,v"
' Open up a new spreadsheet from the above URL.
' Specify the CSV filter with options that decode the CSV format comming back from Yahoo.
' Specify the Hidden property so that the spreadsheet does not appear on the screen.
oCalcDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0,_
Array( MakePropertyValue( "FilterName", "Text - txt - csv (StarCalc)" ),_
MakePropertyValue( "FilterOptions", "44,34,SYSTEM,1,1/10/2/10/3/10/4/10/5/10/6/10/7/10/8/10/9/10" ),_
MakePropertyValue( "Hidden", True ) ) )
' 20170520 - change True to False for debug
Do Until oCalcDoc.IsLoaded
wait(100)
Loop
' Get the first sheet of the Calc document.
oSheet = oCalcDoc.getSheets().getByIndex( 0 )
oCell = oSheet.getCellRangeByName("K1")
oCell.setString("")
oCell.setFormula("=COUNTA(A2:A3737)")
iCount = oCell.getValue()
' 20170522 - convert unix timestamp to date in Google finance history OSheet
' also swap Open / close price
Dim iRow
Dim tempCell
Dim tempint as double
Dim iUnixTime
for iRow = 9 to iCount + 1
oCell = oSheet.getCellRangeByName("B" & CSTR(iRow))
tempCell = oCell.getValue() ' tempCell = B[i]
oCell.setValue(oSheet.getCellRangeByName("E" & CSTR(iRow)).getValue()) ' B[i] CLOSE = E[i] OPEN
oSheet.getCellRangeByName("E" & CSTR(iRow)).setValue(tempCell) ' E[i] = tempCell
oSheet.getCellRangeByName("G" & CSTR(iRow)).setValue(tempCell) ' G[i] = tempCell adjclose = close
' convert unix timestamp in google finance getprices to date
' =IF(LEFT(A9,1)="a", INT(VALUE(RIGHT(A9,10))/86400) + DATE(1970,1,1), IF(LEFT(A8,1)="a", G8+A9, G8+A9-A8))
oCell = oSheet.getCellRangeByName("A" & CSTR(iRow))
if LEFT(oCell.getString(),1) = "a" then
tempint = RIGHT(oCell.getString(),10)
iUnixTime = INT(tempint/86400) + DATEVALUE("1970-01-01")
oCell.setValue(iUnixTime)
else
oCell.setValue(iUnixTime + oCell.getValue())
endif
next
' v1_14 - use cellrange copy
' OldPosition = "A2:G" & CSTR(1+iCount) ' "A2:G90"
' 20170522 - for google finance, copy A9:
OldPosition = "A9:G" & CSTR(1+iCount) ' "A9:G90"
oSource = oSheet.getCellRangeByName(OldPosition)
' NewPosition = "I" & CSTR(1+iRow) & ":J" & CSTR(1+iRow) ' "I18:J18"
' print "1+iRow=", 1+iRow, " NewPosition=", NewPosition
' oTargetSheet = ThisComponent.Sheets.getByName("stockprice")
'oTarget = oTargetSheet.getCellRangeByName(NewPosition)
' NewPosition = "A37:G" & CSTR(36+iCount) ' "A37:G90"
' 20170522 - for google finance, end row - 7
iCount = iCount - 7
NewPosition = "A37:G" & CSTR(36+iCount) ' "A37:G90"
oTarget = oChartSheet.getCellRangeByName(NewPosition)
oTarget.DataArray = oSource.DataArray
' Be sure to close the spreadsheet, because it is hidden, and the user cannot close it.
' 20170520 - do not close for debug
oCalcDoc.close( True )
ThisComponent.calculateAll()
-----------------------------------------------------
'20170520 - try google instead of yahoo
' cURL = "http://ichart.finance.yahoo.com/table.csv?s=" & cSymbols & "&a=" & cStartMonth & "&b=" & cStartDay & "&c=" & cStartYear & "&d=" & cEndMonth & "&e=" & cEndDay & "&f=" & cEndYear & "&g=" & cGranularity & "&ignore=.csv"
cURL = "https://www.google.com/finance/getprices?q=" & LEFT(cSymbols,4) & "&x=HKG&i=86400&p=5Y&f=d,c,h,l,o,v"
' Open up a new spreadsheet from the above URL.
' Specify the CSV filter with options that decode the CSV format comming back from Yahoo.
' Specify the Hidden property so that the spreadsheet does not appear on the screen.
oCalcDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0,_
Array( MakePropertyValue( "FilterName", "Text - txt - csv (StarCalc)" ),_
MakePropertyValue( "FilterOptions", "44,34,SYSTEM,1,1/10/2/10/3/10/4/10/5/10/6/10/7/10/8/10/9/10" ),_
MakePropertyValue( "Hidden", True ) ) )
' 20170520 - change True to False for debug
Do Until oCalcDoc.IsLoaded
wait(100)
Loop
' Get the first sheet of the Calc document.
oSheet = oCalcDoc.getSheets().getByIndex( 0 )
oCell = oSheet.getCellRangeByName("K1")
oCell.setString("")
oCell.setFormula("=COUNTA(A2:A3737)")
iCount = oCell.getValue()
' 20170522 - convert unix timestamp to date in Google finance history OSheet
' also swap Open / close price
Dim iRow
Dim tempCell
Dim tempint as double
Dim iUnixTime
for iRow = 9 to iCount + 1
oCell = oSheet.getCellRangeByName("B" & CSTR(iRow))
tempCell = oCell.getValue() ' tempCell = B[i]
oCell.setValue(oSheet.getCellRangeByName("E" & CSTR(iRow)).getValue()) ' B[i] CLOSE = E[i] OPEN
oSheet.getCellRangeByName("E" & CSTR(iRow)).setValue(tempCell) ' E[i] = tempCell
oSheet.getCellRangeByName("G" & CSTR(iRow)).setValue(tempCell) ' G[i] = tempCell adjclose = close
' convert unix timestamp in google finance getprices to date
' =IF(LEFT(A9,1)="a", INT(VALUE(RIGHT(A9,10))/86400) + DATE(1970,1,1), IF(LEFT(A8,1)="a", G8+A9, G8+A9-A8))
oCell = oSheet.getCellRangeByName("A" & CSTR(iRow))
if LEFT(oCell.getString(),1) = "a" then
tempint = RIGHT(oCell.getString(),10)
iUnixTime = INT(tempint/86400) + DATEVALUE("1970-01-01")
oCell.setValue(iUnixTime)
else
oCell.setValue(iUnixTime + oCell.getValue())
endif
next
' v1_14 - use cellrange copy
' OldPosition = "A2:G" & CSTR(1+iCount) ' "A2:G90"
' 20170522 - for google finance, copy A9:
OldPosition = "A9:G" & CSTR(1+iCount) ' "A9:G90"
oSource = oSheet.getCellRangeByName(OldPosition)
' NewPosition = "I" & CSTR(1+iRow) & ":J" & CSTR(1+iRow) ' "I18:J18"
' print "1+iRow=", 1+iRow, " NewPosition=", NewPosition
' oTargetSheet = ThisComponent.Sheets.getByName("stockprice")
'oTarget = oTargetSheet.getCellRangeByName(NewPosition)
' NewPosition = "A37:G" & CSTR(36+iCount) ' "A37:G90"
' 20170522 - for google finance, end row - 7
iCount = iCount - 7
NewPosition = "A37:G" & CSTR(36+iCount) ' "A37:G90"
oTarget = oChartSheet.getCellRangeByName(NewPosition)
oTarget.DataArray = oSource.DataArray
' Be sure to close the spreadsheet, because it is hidden, and the user cannot close it.
' 20170520 - do not close for debug
oCalcDoc.close( True )
ThisComponent.calculateAll()
-----------------------------------------------------
2017年5月17日 星期三
20170517 首次買入粵海投資(0270) @11.20
在港股進入小時代(>25000點)後,正常操作是沽貨套現。但今天 首次買入粵海投資(0270) @11.20。原因是它是在我watchlist之中,而買入價也到了趨勢系統的下限。據聞因百麗(1880)打算私有化,粵海投資(0270)可能成為下次替代成為恆指成份股。
2017年5月10日 星期三
20170510 恆指終上二萬五 - 又套現盈富(2800.hk) @25.20
今天恆指終上二萬五 - 又套現盈富(2800.hk) @25.20。餘下的盈富不再放了,除非到了28000點。下個放的是匯豐,大約到$70吧!
2017年5月3日 星期三
港股選股器
今天找到一個免費的港股選股器:https://hk.investing.com/stock-screener/
便用它做了以下選股:
5年平均股息收益率 4.00 - 18.66
市值和賬面有形資產比率 (MRQ) 0.07 - 2.50
長期負債股權比 (MRQ) 0.00 - 25.00
淨利率 (5YA) 15.00 - 2.80K
股息收益率 (%) 3.50 - 43.84
市值 3.00B - 2354.17B
---------------------------------------------------
篩選結果 (19) + (extra 4 near miss)
其中另外4個股是near miss,可能是息率或負債稍差。但可放入觀察名單內。
另外選股條件沒有股東權益回報率(ROE%)。 若考慮5年平均ROE >15%更好。
又轉以下2015年12月信報文章:
便用它做了以下選股:
5年平均股息收益率 4.00 - 18.66
市值和賬面有形資產比率 (MRQ) 0.07 - 2.50
長期負債股權比 (MRQ) 0.00 - 25.00
淨利率 (5YA) 15.00 - 2.80K
股息收益率 (%) 3.50 - 43.84
市值 3.00B - 2354.17B
---------------------------------------------------
篩選結果 (19) + (extra 4 near miss)
名稱 | 代號 | 最新 | 漲跌幅% | 市值 | 成交量 |
中銀香港 | 2388 | 32.2 | 0.63% | 340.44B | 7.70M |
恒生銀行 | 0011 | 158.1 | 0.25% | 302.26B | 575.85K |
電能實業 | 0006 | 70.05 | 0.07% | 149.51B | 3.98M |
领展房产基金 | 0823 | 55.85 | -0.18% | 123.60B | 2.60M |
信和置業 | 0083 | 13.1 | -0.61% | 82.73B | 2.49M |
建滔積層板 (1) | 1888 | 9.6 | 2.35% | 29.38B | 6.40M |
合和實業 | 0054 | 29.2 | -1.68% | 25.40B | 295.11K |
合和公路基建 | 0737 | 4.45 | -1.11% | 13.71B | 999.55K |
金界控股 | 3918 | 4.31 | 0.00% | 10.60B | 1.23M |
海港企業 | 0051 | 14.18 | -0.28% | 10.05B | 3.00K |
美麗華酒店 (2) | 0071 | 17.06 | 0.71% | 9.86B | 68.00K |
凱聯國際酒店 | 0105 | 23.45 | 0.64% | 8.44B | 2.00K |
陽光房地產基金 | 0435 | 4.83 | 0.00% | 7.92B | 1.03M |
特步國際 (3) | 1368 | 3.09 | -0.32% | 6.86B | 1.81M |
湯臣集團 | 0258 | 3.56 | -3.78% | 6.11B | 756.43K |
中國利郎 | 1234 | 4.93 | 0.61% | 5.96B | 1.21M |
廖創興企業 | 0194 | 12.3 | 0.16% | 4.66B | 320.00K |
大昌集團 | 0088 | 7.41 | 1.23% | 4.58B | 102.99K |
天德地產 | 0266 | 8.85 | 0.45% | 4.20B | 17.26K |
大眾金融控股 | 0626 | 3.6 | 0.00% | 3.95B | 124.00K |
金利來集團 | 0533 | 3.3 | -0.30% | 3.24B | 91.00K |
香港小輪(集團) | 0050 | 9.03 | 0.44% | 3.22B | 79.50K |
惠記集團 (4) | 0610 | 3.79 | 0.26% | 3.01B | 428.00K |
其中另外4個股是near miss,可能是息率或負債稍差。但可放入觀察名單內。
另外選股條件沒有股東權益回報率(ROE%)。 若考慮5年平均ROE >15%更好。
又轉以下2015年12月信報文章:
【360選股器】學股神睇埋ROE
2015年好快就過,相信唔少投資者正準備部署明年選股,會特別留意基本因素較好嘅股份。散戶一般都會睇市盈率(PE)及息率,認為低PE,高息率可以睇高一線,卻忽略了其他重要嘅基本分析數據。
好似股神畢非德好重視嘅股東權益回報率(ROE),大家不妨多加留意。股神講過,ROE低於15%的公司,基本上不會予以考慮。事實上,現時部份外資券商分析員,都用市賬率(PB)跟ROE比較,PB/ROE比率愈低,代表股份越抵買。
最新篩選結果有21隻股份,內銀股佔最多,其次是內房股及REITs;資源類的中海油(00883)及中海油服(02883)都符合篩選條件,而從事鋁產品製造的中國宏橋(01378)也上名,可以留意。當然,大家亦可自行調整一下選項,再看得出結果如何。
信報投資分析部
訂閱:
文章 (Atom)