Compare commits

...
7 Commits
14 changed files with 662 additions and 312 deletions
+41 -3
View File
@@ -22,10 +22,47 @@ There is a file **examples.ods** there too with usage examples and possible argu
You have to check the respective web sites to work out what symbol is the right one for you. If a web site doesn't have
the symbol/asset you want, this extension can't help you either. Having said that, I mostly look at US and West European
equities, ETFs and mutual funds and major FX rates - if you have issues with the data available for other asset or
equities, ETFs and mutual funds and major FX rates - if you have issues with the data available for other assets or
assets in other regions, drop me a line (best to include full URLs and possibly the same asset listed on more than one
site for comparison). While data for last price is most likely consistent across sites, they will differ when it comes to
less well defined data points.
site for comparison). While data for last price is most likely consistent across sites, they may differ for other data
points.
### List of supported data points
You can either specify numbers or names (lower or upper case) - not all bits are available from all sources and they are not necessarily consistent across sources either.
|Name|Number|Yahoo|FT|Google|
| :--- | :--- | :---: | :---: | :---: |
|PREV_CLOSE|5|Yes|Yes|Yes|
|OPEN|6|Yes|Yes|Yes|
|CHANGE|7|Yes|Yes|Yes|
|LAST_PRICE_DATE|8|Yes|Yes|Yes|
|LAST_PRICE_TIME|10|Yes|Yes|Yes|
|CHANGE_IN_PERCENT|11|Yes|Yes|Yes|
|LOW|14|Yes|Yes|Yes|
|HIGH|16|Yes|Yes|Yes|
|LAST_PRICE|21|Yes|Yes|Yes|
|HIGH_52_WEEK|24|Yes|Yes|Yes|
|LOW_52_WEEK|26|Yes|Yes|Yes|
|MARKET_CAP|27|Yes|Yes|Yes|
|VOLUME|35|Yes|Yes|No|
|AVG_DAILY_VOL_3MONTH|39|Yes|Yes|No|
|BETA|67|Yes|Yes|No|
|EPS|68|Yes|Yes|No|
|PE_RATIO|69|Yes|Yes|No|
|DIV|70|Yes|Yes|No|
|DIV_YIELD|71|Yes|Yes|No|
|EX_DIV_DATE|72|Yes|Yes|No|
|PAYOUT_RATIO|73|Yes|No|No|
|CLOSE|90|(historic)|No|No|
|ADJ_CLOSE|91|(historic)|No|No|
|SECTOR|98|Yes|Yes|No|
|INDUSTRY|99|Yes|Yes|No|
|TICKER|101|Yes|Yes|Yes|
|EXCHANGE|102|Yes|No|Yes|
|CURRENCY|103|Yes|Yes|Yes|
|NAME|104|Yes|Yes|Yes|
|TIMEZONE|105|Yes|Yes|Yes|
### Dealing with missing data:
@@ -57,6 +94,7 @@ python3 src/test_google.py
### Tested with:
- Debian 10.3 / LibreOffice Calc 6.1.5.2 / Python 3.7.3
- Ubuntu 20.04 / LibreOffice Calc 6.4.3.2 / Python 3.8.2
- Ubuntu 19.10 / LibreOffice Calc 6.3.5.2 / Python 3.7.6
- Ubuntu 19.04 / LibreOffice Calc 6.2 / Python 3.7.3
- Ubuntu 18.04 / LibreOffice Calc 6 / Python 3.6.7
BIN
View File
Binary file not shown.
+64 -21
View File
@@ -48,22 +48,35 @@ class BaseClient:
os.makedirs(self.basedir, exist_ok=True)
user_agents = [
'Mozilla/5.0 (Windows NT 6.1; rv:73.0) Gecko/20100101 Firefox/73.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:74.0) Gecko/20100101 Firefox/74.0',
'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0'
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0',
'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0',
'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0',
'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4104.0 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4149.0 Safari/537.36'
]
self.default_headers = {
'User-Agent': random.sample(user_agents, 1)[0],
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'en-US,en;q=0.5'
'Accept-Language': 'en-US,en;q=0.5',
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0'
}
self.response = None
def request(self, method: str, url: str, data=None, headers={}, cookies=[], **kwargs):
_headers = self.default_headers.copy()
@@ -122,13 +135,13 @@ class BaseClient:
def urlopen(self, url, redirect=True, data=None, headers={}, cookies=[], **kwargs):
response = self.request('POST' if data else 'GET', url, data, headers, cookies, **kwargs)
text = response.read()
self.response = self.request('POST' if data else 'GET', url, data, headers, cookies, **kwargs)
text = self.response.read()
# Allow two redirects: used by Yahoo for some cookie based consent
if 300 <= response.status < 400:
location = response.getheader('Location')
if 300 <= self.response.status < 400:
location = self.response.getheader('Location')
if location and redirect:
@@ -136,11 +149,11 @@ class BaseClient:
scheme, _, host, path = url.split('/', 3)
location = '{}//{}{}'.format(scheme, host, location)
response = self.request('POST' if data else 'GET', location, data, headers, cookies, **kwargs)
text = response.read()
self.response = self.request('POST' if data else 'GET', location, data, headers, cookies, **kwargs)
text = self.response.read()
if 300 <= response.status < 400:
location = response.getheader('Location')
if 300 <= self.response.status < 400:
location = self.response.getheader('Location')
if location and redirect:
@@ -148,21 +161,21 @@ class BaseClient:
scheme, _, host, path = url.split('/', 3)
location = '{}//{}{}'.format(scheme, host, location)
response = self.request('POST' if data else 'GET', location, data, headers, cookies, **kwargs)
text = response.read()
self.response = self.request('POST' if data else 'GET', location, data, headers, cookies, **kwargs)
text = self.response.read()
else:
raise RedirectException(location)
else:
raise RedirectException(location)
if response.status >= 400:
raise HttpException(url, response.status)
if self.response.status >= 400:
raise HttpException(url, self.response.status)
if response.getheader('Content-Encoding') == 'gzip':
if self.response.getheader('Content-Encoding') == 'gzip':
text = gzip.decompress(text)
content_type = response.headers.get_content_charset()
content_type = self.response.headers.get_content_charset()
if content_type is None:
content_type = 'utf-8'
text = codecs.decode(text, encoding=content_type, errors='ignore')
@@ -228,8 +241,32 @@ class BaseClient:
elif datacode == Datacode.VOLUME.value and Datacode.VOLUME in data:
return data[Datacode.VOLUME]
elif datacode == Datacode.AVG_DAILY_VOL_3MOMTH.value and Datacode.AVG_DAILY_VOL_3MOMTH in data:
return data[Datacode.AVG_DAILY_VOL_3MOMTH]
elif datacode == Datacode.AVG_DAILY_VOL_3MONTH.value and Datacode.AVG_DAILY_VOL_3MONTH in data:
return data[Datacode.AVG_DAILY_VOL_3MONTH]
elif datacode == Datacode.BETA.value and Datacode.BETA in data:
return data[Datacode.BETA]
elif datacode == Datacode.EPS.value and Datacode.EPS in data:
return data[Datacode.EPS]
elif datacode == Datacode.PE_RATIO.value and Datacode.PE_RATIO in data:
return data[Datacode.PE_RATIO]
elif datacode == Datacode.DIV.value and Datacode.DIV in data:
return data[Datacode.DIV]
elif datacode == Datacode.DIV_YIELD.value and Datacode.DIV_YIELD in data:
return data[Datacode.DIV_YIELD]
elif datacode == Datacode.EX_DIV_DATE.value and Datacode.EX_DIV_DATE in data:
if data[Datacode.EX_DIV_DATE]:
return data[Datacode.EX_DIV_DATE].isoformat()
else:
return data[Datacode.EX_DIV_DATE]
elif datacode == Datacode.PAYOUT_RATIO.value and Datacode.PAYOUT_RATIO in data:
return data[Datacode.PAYOUT_RATIO]
elif datacode == Datacode.CLOSE.value and Datacode.CLOSE in data:
return data[Datacode.CLOSE]
@@ -237,6 +274,12 @@ class BaseClient:
elif datacode == Datacode.ADJ_CLOSE.value and Datacode.ADJ_CLOSE in data:
return data[Datacode.ADJ_CLOSE]
elif datacode == Datacode.SECTOR.value and Datacode.SECTOR in data:
return data[Datacode.SECTOR]
elif datacode == Datacode.INDUSTRY.value and Datacode.INDUSTRY in data:
return data[Datacode.INDUSTRY]
elif datacode == Datacode.TICKER.value and Datacode.TICKER in data:
return data[Datacode.TICKER]
+12 -1
View File
@@ -29,11 +29,22 @@ class Datacode(Enum):
MARKET_CAP = 27
VOLUME = 35
AVG_DAILY_VOL_3MOMTH = 39
AVG_DAILY_VOL_3MONTH = 39
BETA = 67
EPS = 68
PE_RATIO = 69
DIV = 70
DIV_YIELD = 71
EX_DIV_DATE = 72
PAYOUT_RATIO = 73
CLOSE = 90
ADJ_CLOSE = 91
SECTOR = 98
INDUSTRY = 99
TICKER = 101
EXCHANGE = 102
CURRENCY = 103
+10 -4
View File
@@ -88,9 +88,12 @@ class FinancialsImpl(unohelper.Base, Financials):
return 'Datacode is empty'
try:
datacode = int(float(str(datacode).strip()))
dc = str(datacode).strip().upper()
if dc in Datacode.__members__:
dc = Datacode[dc].value
datacode = int(float(dc))
except:
return 'Datacode is not a number'
return 'Datacode is invalid'
if not Datacode.has_value(datacode):
return 'Datacode {} not supported'.format(datacode)
@@ -146,9 +149,12 @@ class FinancialsImpl(unohelper.Base, Financials):
return 'Date is empty'
try:
datacode = int(float(str(datacode).strip()))
dc = str(datacode).strip().upper()
if dc in Datacode.__members__:
dc = Datacode[dc].value
datacode = int(float(dc))
except:
return 'Datacode {} is not a number'.format(datacode)
return 'Datacode {} is invalid'.format(datacode)
if not Datacode.has_value(datacode):
return 'Datacode {} not supported'.format(datacode)
+82 -23
View File
@@ -7,7 +7,7 @@
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
import dateutil
import dateutil.parser
import html
import logging
import os
@@ -107,10 +107,17 @@ class FT(BaseClient):
tick[Datacode.MARKET_CAP] = None
tick[Datacode.EXCHANGE] = None
tick[Datacode.AVG_DAILY_VOL_3MOMTH] = None
tick[Datacode.AVG_DAILY_VOL_3MONTH] = None
tick[Datacode.BETA] = None
tick[Datacode.EPS] = None
tick[Datacode.PE_RATIO] = None
tick[Datacode.DIV] = None
tick[Datacode.DIV_YIELD] = None
tick[Datacode.EX_DIV_DATE] = None
tick[Datacode.PAYOUT_RATIO] = None
try:
r = '<div class="mod-tearsheet-overview__header"><h1 [^>]*>(.*?)</h1>'
r = '<h1 class="mod-tearsheet-overview__header__name mod-tearsheet-overview__header__name--large">(.*?)</h1>'
match = re.compile(r, flags=re.DOTALL).search(text)
if not match:
return None
@@ -126,16 +133,26 @@ class FT(BaseClient):
tick[Datacode.TICKER] = self.save_wrapper(
lambda: html.unescape(match.group(1)).strip())
r = '<span [^>]*>Price \(([A-Z]+)\)</span><span [^>]*>([0-9,\.]+)</span>'
r = '<div class="mod-tearsheet-overview__esi">(.*?)<i.*?</i>(.*?)<'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
start = match.span(0)[1]
tick[Datacode.CURRENCY] = self.save_wrapper(
tick[Datacode.SECTOR] = self.save_wrapper(
lambda: html.unescape(match.group(1)).strip())
tick[Datacode.INDUSTRY] = self.save_wrapper(
lambda: html.unescape(match.group(2)).strip())
r = r'<span [^>]*>Price \(([A-Z]+|--)\)</span><span [^>]*>([0-9,\.]+)</span>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
start = match.span(0)[1]
if match.group(1) != '--':
tick[Datacode.CURRENCY] = self.save_wrapper(
lambda: html.unescape(match.group(1)).strip())
tick[Datacode.LAST_PRICE] = self.save_wrapper(
lambda: float(html.unescape(match.group(2)).replace(',', '').strip()))
r = '<span[^>]*>Today\'s Change</span><span[^>]*><span[^>]*>(?:<i[^>]*></i>)?([0-9,\.-]+) */ *([0-9,\.-]+)%</span>'
r = r'<span[^>]*>Today\'s Change</span><span[^>]*><span[^>]*>(?:<i[^>]*></i>)?([0-9,\.-]+) */ *([0-9,\.-]+)%</span>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
start = match.span(0)[1]
@@ -144,14 +161,21 @@ class FT(BaseClient):
tick[Datacode.CHANGE_IN_PERCENT] = self.save_wrapper(
lambda: float(html.unescape(match.group(2)).replace(',', '').strip()))
r = '<span[^>]*>Shares traded</span><span[^>]*>([0-9mk,\.]+)</span>'
r = r'<span[^>]*>Shares traded</span><span[^>]*>([0-9mk,\.]+)</span>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
start = match.span(0)[1]
tick[Datacode.VOLUME] = self.save_wrapper(
lambda: handle_abbreviations(html.unescape(match.group(1))))
r = '<span[^>]*>52 week range</span><span[^>]*>([0-9,\.]+) *- *([0-9,\.]+)</span>'
r = r'<span[^>]*>Beta</span><span[^>]*>([0-9,\.]+)</span>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
start = match.span(0)[1]
tick[Datacode.BETA] = self.save_wrapper(
lambda: handle_abbreviations(html.unescape(match.group(1))))
r = r'<span[^>]*>52 week range</span><span[^>]*>([0-9,\.]+) *- *([0-9,\.]+)</span>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
start = match.span(0)[1]
@@ -160,10 +184,7 @@ class FT(BaseClient):
tick[Datacode.HIGH_52_WEEK] = self.save_wrapper(
lambda: float(html.unescape(match.group(2)).replace(',', '').strip()))
# <div class="mod-disclaimer">Data delayed at least 15 minutes, as of Apr 13 2020 15:01 BST.</div>
# <div class="mod-disclaimer">.+?as of (.+)\.?</div>
r = '<div class="mod-disclaimer">.+?as of (.+?)\.?</div>'
r = r'<div class="mod-disclaimer">.+?as of (.+?)\.?</div>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
start = match.span(0)[1]
@@ -183,14 +204,14 @@ class FT(BaseClient):
# second attempt at 52 week range
if Datacode.LOW_52_WEEK not in tick or not tick[Datacode.LOW_52_WEEK]:
r = '<span class="mod-ui-range-bar__container__label--lo"><span[^>]*>([0-9,\.]+)</span>'
r = r'<span class="mod-ui-range-bar__container__label--lo"><span[^>]*>([0-9,\.]+)</span>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.LOW_52_WEEK] = self.save_wrapper(
lambda: float(html.unescape(match.group(1)).replace(',', '').strip()))
if Datacode.HIGH_52_WEEK not in tick or not tick[Datacode.HIGH_52_WEEK]:
r = '<span class="mod-ui-range-bar__container__label--hi"><span[^>]*>([0-9,\.]+)</span>'
r = r'<span class="mod-ui-range-bar__container__label--hi"><span[^>]*>([0-9,\.]+)</span>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.HIGH_52_WEEK] = self.save_wrapper(
@@ -202,42 +223,80 @@ class FT(BaseClient):
if match:
start = match.span(0)[1]
r = '<th>Open</th><td>([0-9,\.]+)</td>'
r = r'<th>Open</th><td>([0-9,\.]+)</td>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.OPEN] = self.save_wrapper(
lambda: float(html.unescape(match.group(1)).replace(',', '').strip()))
r = '<th>High</th><td>([0-9,\.]+)</td>'
r = r'<th>High</th><td>([0-9,\.]+)</td>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.HIGH] = self.save_wrapper(
lambda: float(html.unescape(match.group(1)).replace(',', '').strip()))
r = '<th>Low</th><td>([0-9,\.]+)</td>'
r = r'<th>Low</th><td>([0-9,\.]+)</td>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.LOW] = self.save_wrapper(
lambda: float(html.unescape(match.group(1)).replace(',', '').strip()))
r = '<th>\s*Previous close\s*</th><td>\s*([0-9,\.]+)\s*</td>'
r = r'<th>\s*Previous close\s*</th><td>\s*([0-9,\.]+)\s*</td>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.PREV_CLOSE] = self.save_wrapper(
lambda: float(html.unescape(match.group(1)).replace(',', '').strip()))
r = '<th>\s*Average volume\s*</th><td>\s*([0-9,\.btnm]+)\s*</td>'
r = r'<th>\s*Average volume\s*</th><td>\s*([0-9,\.btnm]+)\s*</td>'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.AVG_DAILY_VOL_3MOMTH] = self.save_wrapper(
tick[Datacode.AVG_DAILY_VOL_3MONTH] = self.save_wrapper(
lambda: handle_abbreviations(html.unescape(match.group(1))))
r = '<th>\s*Market cap\s*</th><td>\s*([0-9,\.btnm]+)\s*<'
r = r'<th>\s*P/E.*?</th><td>\s*([0-9,\.\-]+)\s*<'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
value = html.unescape(match.group(1))
if value == '--':
tick[Datacode.PE_RATIO] = 0.0
else:
tick[Datacode.PE_RATIO] = self.save_wrapper(
lambda: float(value))
r = r'<th>\s*Market cap\s*</th><td>\s*([0-9,\.btnm]+)\s*<'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.MARKET_CAP] = self.save_wrapper(
lambda: handle_abbreviations(html.unescape(match.group(1))))
r = r'<th>\s*EPS.*?</th><td>\s*([0-9,\.\-]+)\s*<'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.EPS] = self.save_wrapper(
lambda: float(html.unescape(match.group(1))))
r = r'<th>\s*Annual div.*?</th><td>\s*([0-9,\.]+)\s*<'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.DIV] = self.save_wrapper(
lambda: float(html.unescape(match.group(1))))
r = r'<th>\s*Annual div yield.*?</th><td>\s*([0-9,\.]+)%\s*<'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
tick[Datacode.DIV_YIELD] = self.save_wrapper(
lambda: float(html.unescape(match.group(1))))
r = r'<th>\s*Div ex-date\s*</th><td><span[^>]*>(.*?)</span><'
match = re.compile(r, flags=re.DOTALL).search(text, start)
if match:
try:
value = html.unescape(match.group(1)).strip()
dt = dateutil.parser.parse(value, tzinfos=whois_timezone_info)
tick[Datacode.EX_DIV_DATE] = dt.date()
except BaseException as e:
pass
except BaseException as e:
logger.error(traceback.format_exc())
return f'FT.getRealtime({ticker}, {datacode}) - process: {str(e)}'
@@ -252,9 +311,9 @@ class FT(BaseClient):
def guess_asset_class(self, ticker):
if len(ticker) == 6:
if ticker[0:2] in ['USD', 'EUR', 'GBP']:
if ticker[0:2] in ['USD', 'EUR', 'GBP', 'JPY', 'CHF']:
return 'currencies'
if ticker[3:5] in ['USD', 'EUR', 'GBP']:
if ticker[3:5] in ['USD', 'EUR', 'GBP', 'JPY', 'CHF']:
return 'currencies'
colon_count = ticker.count(':')
+1 -1
View File
@@ -14,7 +14,7 @@ import os
cur_dir = os.getcwd()
addin_id = "com.financials.getinfo"
addin_version = "2.0.0"
addin_version = "2.2.1"
addin_displayname = "Financial Market Extension"
addin_publisher_link = "https://github.com/cmallwitz/Financials-Extension"
addin_publisher_name = "The Publisher"
+3 -3
View File
@@ -124,7 +124,7 @@ class Google(BaseClient):
tick[Datacode.MARKET_CAP] = None
tick[Datacode.EXCHANGE] = None
tick[Datacode.AVG_DAILY_VOL_3MOMTH] = None
tick[Datacode.AVG_DAILY_VOL_3MONTH] = None
try:
r = '<span[^>]+role="heading"[^>]+>(.*?)</span>'
@@ -138,10 +138,10 @@ class Google(BaseClient):
tick[Datacode.NAME] = self.save_wrapper(
lambda: html.unescape(un_span(match.group(1)).strip()))
r = '<div [^>]*>(.*?)</div>'
# next div is TICKER
r = '<div [^>]*><div [^>]*>(.*?)</div></div>'
pattern = re.compile(r)
# first div is TICKER
match = pattern.search(text, start)
if not match:
return 'Google.getRealtime({}, {}) - no match'.format(ticker, datacode)
+47 -50
View File
@@ -8,20 +8,25 @@
# Updated 8 Jan 2007 - fixed dict grouping bug, and made elements and
# members optional in array and object collections
#
# Updated 9 Aug 2016 - use more current pyparsing constructs/idioms
#
# https://github.com/pyparsing/pyparsing/blob/master/examples/jsonParser.py - revision 53d1b4a on 1 Nov 2019
json_bnf = """
object
{ members }
{}
members
string : value
members , string : value
array
object
{ members }
{}
members
string : value
members , string : value
array
[ elements ]
[]
elements
value
elements , value
value
[]
elements
value
elements , value
value
string
number
object
@@ -31,40 +36,38 @@ value
null
"""
from pyparsing import *
import pyparsing as pp
from pyparsing import pyparsing_common as ppc
TRUE = Keyword("true").setParseAction(replaceWith(True))
FALSE = Keyword("false").setParseAction(replaceWith(False))
NULL = Keyword("null").setParseAction(replaceWith(None))
jsonString = dblQuotedString.setParseAction(removeQuotes)
jsonNumber = Combine(Optional('-') + ('0' | Word('123456789', nums)) +
Optional('.' + Word(nums)) +
Optional(Word('eE', exact=1) + Word(nums + '+-', nums)))
def make_keyword(kwd_str, kwd_value):
return pp.Keyword(kwd_str).setParseAction(pp.replaceWith(kwd_value))
jsonObject = Forward()
jsonValue = Forward()
jsonElements = delimitedList(jsonValue)
jsonArray = Group(Suppress('[') + Optional(jsonElements) + Suppress(']'))
jsonValue << (jsonString | jsonNumber | Group(jsonObject) | jsonArray | TRUE | FALSE | NULL)
memberDef = Group(jsonString + Suppress(':') + jsonValue)
jsonMembers = delimitedList(memberDef)
jsonObject << Dict(Suppress('{') + Optional(jsonMembers) + Suppress('}'))
jsonComment = cppStyleComment
TRUE = make_keyword("true", True)
FALSE = make_keyword("false", False)
NULL = make_keyword("null", None)
LBRACK, RBRACK, LBRACE, RBRACE, COLON = map(pp.Suppress, "[]{}:")
jsonString = pp.dblQuotedString().setParseAction(pp.removeQuotes)
jsonNumber = ppc.number()
jsonObject = pp.Forward()
jsonValue = pp.Forward()
jsonElements = pp.delimitedList(jsonValue)
jsonArray = pp.Group(LBRACK + pp.Optional(jsonElements, []) + RBRACK)
jsonValue << (
jsonString | jsonNumber | pp.Group(jsonObject) | jsonArray | TRUE | FALSE | NULL
)
memberDef = pp.Group(jsonString + COLON + jsonValue)
jsonMembers = pp.delimitedList(memberDef)
jsonObject << pp.Dict(LBRACE + pp.Optional(jsonMembers) + RBRACE)
jsonComment = pp.cppStyleComment
jsonObject.ignore(jsonComment)
def convertNumbers(s, l, toks):
n = toks[0]
try:
return int(n)
except ValueError as ve:
return float(n)
jsonNumber.setParseAction(convertNumbers)
if __name__ == "__main__":
testdata = """
{
@@ -72,7 +75,7 @@ if __name__ == "__main__":
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList":
"GlossList":
{
"ID": "SGML",
"SortAs": "SGML",
@@ -96,20 +99,14 @@ if __name__ == "__main__":
}
"""
import pprint
results = jsonObject.parseString(testdata)
pprint.pprint(results.asList())
print
results.pprint()
print()
def testPrint(x):
print
type(x), repr(x)
print(type(x), repr(x))
print
results.glossary.GlossDiv.GlossList.keys()
print(list(results.glossary.GlossDiv.GlossList.keys()))
testPrint(results.glossary.title)
testPrint(results.glossary.GlossDiv.GlossList.ID)
testPrint(results.glossary.GlossDiv.GlossList.FalseValue)
+221 -130
View File
@@ -13,7 +13,7 @@ import sys
import unittest
import financials
from datacode import Datacode
import testutils
financials = financials.createInstance(None)
@@ -23,207 +23,298 @@ logging.basicConfig(level=logging.ERROR)
class Test(unittest.TestCase):
def test_currency(self):
s = financials.getRealtime('EURGBP', Datacode.CURRENCY.value, 'FT')
self.assertEqual(type(s), str, 'test_currency CURRENCY')
s = financials.getRealtime('EURGBP', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_currency LAST_PRICE')
s = financials.getRealtime('EURGBP', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_currency LAST_PRICE')
s = financials.getRealtime('EURGBP', 'CURRENCY', 'FT')
self.assertEqual(str, type(s), 'test_currency CURRENCY')
def test_US_equity(self):
s = financials.getRealtime('INTC:NSQ', Datacode.CHANGE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity CHANGE {}'.format(s))
s = financials.getRealtime('INTC:NSQ', 'CHANGE', 'FT')
self.assertEqual(float, type(s), 'test_US_equity CHANGE {}'.format(s))
s = financials.getRealtime('INTC:NSQ', Datacode.CHANGE_IN_PERCENT.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity CHANGE_IN_PERCENT {}'.format(s))
s = financials.getRealtime('INTC:NSQ', 'CHANGE_IN_PERCENT', 'FT')
self.assertEqual(float, type(s), 'test_US_equity CHANGE_IN_PERCENT {}'.format(s))
s = financials.getRealtime('INTC:NSQ', Datacode.AVG_DAILY_VOL_3MOMTH.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity AVG_DAILY_VOL_3MOMTH {}'.format(s))
s = financials.getRealtime('INTC:NSQ', 'AVG_DAILY_VOL_3MONTH', 'FT')
self.assertEqual(float, type(s), 'test_US_equity AVG_DAILY_VOL_3MONTH {}'.format(s))
s = financials.getRealtime('INTC:NSQ', Datacode.MARKET_CAP.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('INTC:NSQ', 'MARKET_CAP', 'FT')
self.assertEqual(float, type(s), 'test_US_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.TICKER.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_US_equity TICKER {}'.format(s))
self.assertEqual(s, 'IBM:NYQ', 'test_realtime_US_equity TICKER {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'TICKER', 'FT')
self.assertEqual(str, type(s), 'test_US_equity TICKER {}'.format(s))
self.assertEqual('IBM:NYQ', s, 'test_US_equity TICKER {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.PREV_CLOSE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity PREV_CLOSE {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'PREV_CLOSE', 'FT')
self.assertEqual(float, type(s), 'test_US_equity PREV_CLOSE {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.OPEN.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity OPEN {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'OPEN', 'FT')
self.assertEqual(float, type(s), 'test_US_equity OPEN {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_US_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.LOW.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity LOW {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'LOW', 'FT')
self.assertEqual(float, type(s), 'test_US_equity LOW {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.HIGH.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity HIGH {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'HIGH', 'FT')
self.assertEqual(float, type(s), 'test_US_equity HIGH {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.VOLUME.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_equity VOLUME {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'VOLUME', 'FT')
self.assertEqual(float, type(s), 'test_US_equity VOLUME {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.NAME.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_US_equity NAME {}'.format(s))
self.assertEqual(s, 'International Business Machines Corp',
'test_realtime_US_equity NAME {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'BETA', 'FT')
self.assertTrue(testutils.is_positive_float(s), 'test_US_equity BETA {}'.format(s))
s = financials.getRealtime('IBM:NYQ', Datacode.TIMEZONE.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_US_equity TIMEZONE {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'EPS', 'FT')
self.assertEqual(float, type(s), 'test_US_equity EPS {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'PE_RATIO', 'FT')
self.assertEqual(float, type(s), 'test_US_equity PE_RATIO {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'DIV', 'FT')
self.assertEqual(float, type(s), 'test_US_equity DIV {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'DIV_YIELD', 'FT')
self.assertEqual(float, type(s), 'test_US_equity DIV_YIELD {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'EX_DIV_DATE', 'FT')
self.assertEqual(str, type(s), 'test_US_equity EX_DIV_DATE {}'.format(s))
self.assertTrue(testutils.is_date(s), 'test_US_equity EX_DIV_DATE {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'PAYOUT_RATIO', 'FT')
self.assertIsNone(s, 'test_US_equity PAYOUT_RATIO {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'NAME', 'FT')
self.assertEqual(str, type(s), 'test_US_equity NAME {}'.format(s))
self.assertEqual(s, 'International Business Machines Corp', 'test_US_equity NAME {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'SECTOR', 'FT')
self.assertEqual(str, type(s), 'test_US_equity SECTOR {}'.format(s))
self.assertEqual(s, 'Technology', 'test_US_equity SECTOR {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'INDUSTRY', 'FT')
self.assertEqual(str, type(s), 'test_US_equity INDUSTRY {}'.format(s))
self.assertEqual(s, 'Software & Computer Services', 'test_US_equity INDUSTRY {}'.format(s))
s = financials.getRealtime('IBM:NYQ', 'TIMEZONE', 'FT')
self.assertEqual(str, type(s), 'test_US_equity TIMEZONE {}'.format(s))
def test_US_mutuals(self):
s = financials.getRealtime('VGSLX', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_mutuals LAST_PRICE {}'.format(s))
s = financials.getRealtime('VGSLX', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_US_mutuals LAST_PRICE {}'.format(s))
s = financials.getRealtime('VGSLX', Datacode.NAME.value, 'FT')
self.assertEqual(s, "Vanguard Real Estate Index Fund Admiral Shares",
'test_realtime_US_mutuals NAME {}'.format(s))
s = financials.getRealtime('VGSLX', 'NAME', 'FT')
self.assertEqual("Vanguard Real Estate Index Fund Admiral Shares", s, 'test_US_mutuals NAME {}'.format(s))
s = financials.getRealtime('VGSLX', Datacode.CURRENCY.value, 'FT')
self.assertEqual(s, "USD", 'test_realtime_US_mutuals CURRENCY {}'.format(s))
s = financials.getRealtime('VGSLX', 'CURRENCY', 'FT')
self.assertEqual('USD', s, 'test_US_mutuals CURRENCY {}'.format(s))
s = financials.getRealtime('VGSLX', Datacode.CHANGE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_mutuals CHANGE {}'.format(s))
s = financials.getRealtime('VGSLX', 'CHANGE', 'FT')
self.assertEqual(float, type(s), 'test_US_mutuals CHANGE {}'.format(s))
s = financials.getRealtime('VGSLX', Datacode.CHANGE_IN_PERCENT.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_mutuals CHANGE_IN_PERCENT {}'.format(s))
s = financials.getRealtime('VGSLX', 'CHANGE_IN_PERCENT', 'FT')
self.assertEqual(float, type(s), 'test_US_mutuals CHANGE_IN_PERCENT {}'.format(s))
s = financials.getRealtime('VGSLX', Datacode.TIMEZONE.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_US_mutuals TIMEZONE {}'.format(s))
s = financials.getRealtime('VFIAX', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_US_mutuals LAST_PRICE {}'.format(s))
s = financials.getRealtime('VFIAX', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_US_mutuals LAST_PRICE {}'.format(s))
s = financials.getRealtime('VFIAX', 'LAST_PRICE_DATE', 'FT')
self.assertEqual(str, type(s), 'test_US_mutuals LAST_PRICE_DATE {}'.format(s))
self.assertTrue(testutils.is_date(s), 'test_US_mutuals LAST_PRICE_DATE {}'.format(s))
s = financials.getRealtime('VFIAX', Datacode.LAST_PRICE_DATE.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_US_mutuals LAST_PRICE_DATE {}'.format(s))
s = financials.getRealtime('VFIAX', Datacode.LAST_PRICE_TIME.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_US_mutuals LAST_PRICE_TIME {}'.format(s))
s = financials.getRealtime('VFIAX', 'LAST_PRICE_TIME', 'FT')
self.assertEqual(str, type(s), 'test_US_mutuals LAST_PRICE_TIME {}'.format(s))
def test_UK_ETF(self):
s = financials.getRealtime('VERX:LSE:GBP', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_UK_ETF LAST_PRICE {}'.format(s))
s = financials.getRealtime('CSP1:LSE:GBX', 'NAME', 'FT')
self.assertEqual(str, type(s), 'test_UK_ETF NAME {}'.format(s))
self.assertEqual('iShares Core S&P 500 UCITS ETF USD (Acc)', s, 'test_UK_ETF NAME {}'.format(s))
s = financials.getRealtime('VERX:LSE:GBP', Datacode.TIMEZONE.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_UK_ETF TIMEZONE {}'.format(s))
s = financials.getRealtime('C060:GER:EUR', 'NAME', 'FT')
self.assertEqual(str, type(s), 't_UK_ETF NAME {}'.format(s))
s = financials.getRealtime('CSP1:LSE:GBX', Datacode.NAME.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_UK_ETF NAME {}'.format(s))
self.assertEqual(s, 'iShares Core S&P 500 UCITS ETF USD (Acc)',
'test_realtime_UK_ETF NAME {}'.format(s))
s = financials.getRealtime('VERX:LSE:GBP', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_UK_ETF LAST_PRICE {}'.format(s))
s = financials.getRealtime('C060:GER:EUR', Datacode.NAME.value, 'FT')
self.assertEqual(type(s), str, 't_realtime_UK_ETF NAME {}'.format(s))
s = financials.getRealtime('VERX:LSE:GBP', 'TIMEZONE', 'FT')
self.assertEqual(str, type(s), 'test_UK_ETF TIMEZONE {}'.format(s))
def test_DE_equity(self):
s = financials.getRealtime('SAPX:GER', Datacode.NAME.value, 'FT')
self.assertEqual(s, "SAP SE", 'test_realtime_DE_equity NAME {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'NAME', 'FT')
self.assertEqual('SAP SE', s, 'test_DE_equity NAME {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.TICKER.value, 'FT')
self.assertEqual(s, "SAPX:GER", 'test_realtime_DE_equity TICKER {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'TICKER', 'FT')
self.assertEqual('SAPX:GER', s, 'test_DE_equity TICKER {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.CURRENCY.value, 'FT')
self.assertEqual(s, 'EUR', 'test_realtime_DE_equity CURRENCY {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'CURRENCY', 'FT')
self.assertEqual('EUR', s, 'test_DE_equity CURRENCY {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.TIMEZONE.value, 'FT')
self.assertEqual(type(s), str, 'test_realtime_DE_equity TIMEZONE {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'CHANGE', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity CHANGE {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.CHANGE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity CHANGE {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'CHANGE_IN_PERCENT', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity CHANGE_IN_PERCENT {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.CHANGE_IN_PERCENT.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity CHANGE_IN_PERCENT {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'VOLUME', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity VOLUME {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.VOLUME.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity VOLUME {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'OPEN', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity OPEN {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.OPEN.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity OPEN {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'HIGH', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity HIGH {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.HIGH.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity HIGH {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'LOW', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity LOW {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.LOW.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity LOW {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'PREV_CLOSE', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity PREV_CLOSE {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.PREV_CLOSE.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity PREV_CLOSE {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'MARKET_CAP', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.MARKET_CAP.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'SECTOR', 'FT')
self.assertEqual(str, type(s), 'test_DE_equity SECTOR {}'.format(s))
self.assertEqual(s, 'Technology', 'test_DE_equity SECTOR {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'INDUSTRY', 'FT')
self.assertEqual(str, type(s), 'test_DE_equity INDUSTRY {}'.format(s))
self.assertEqual('Software & Computer Services', s, 'test_DE_equity INDUSTRY {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'LAST_PRICE_DATE', 'FT')
self.assertEqual(str, type(s), 'test_DE_equity LAST_PRICE_DATE {}'.format(s))
self.assertTrue(testutils.is_date(s), 'test_DE_equity LAST_PRICE_DATE {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'TIMEZONE', 'FT')
self.assertEqual(str, type(s), 'test_DE_equity TIMEZONE {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'BETA', 'FT')
self.assertTrue(testutils.is_positive_float(s), 'test_DE_equity BETA {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'EPS', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity EPS {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'PE_RATIO', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity PE_RATIO {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'DIV', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity DIV {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'DIV_YIELD', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity DIV_YIELD {}'.format(s))
s = financials.getRealtime('SAPX:GER', 'EX_DIV_DATE', 'FT')
self.assertEqual(str, type(s), 'test_DE_equity EX_DIV_DATE {}'.format(s))
self.assertTrue(testutils.is_date(s), 'test_DE_equity EX_DIV_DATE {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'NAME', 'FT')
self.assertEqual('Intershop Communications AG', s, 'test_DE_equity NAME {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'BETA', 'FT')
self.assertTrue(testutils.is_positive_float(s), 'test_DE_equity BETA {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'MARKET_CAP', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'EPS', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity EPS {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'PE_RATIO', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity PE_RATIO {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'DIV', 'FT')
self.assertIsNone(s, 'test_DE_equity DIV {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'DIV_YIELD', 'FT')
self.assertIsNone(s, 'test_DE_equity DIV_YIELD {}'.format(s))
s = financials.getRealtime('ISHAX:GER', 'EX_DIV_DATE', 'FT')
self.assertIsNone(s, 'test_DE_equity EX_DIV_DATE {}'.format(s))
def test_TY_equity(self):
s = financials.getRealtime('6503:TYO', Datacode.OPEN.value, 'FT')
self.assertEqual(type(s), float, 'test_TY_equity OPEN {}'.format(s))
s = financials.getRealtime('6503:TYO', 'OPEN', 'FT')
self.assertEqual(float, type(s), 'test_TY_equity OPEN {}'.format(s))
s = financials.getRealtime('6503:TYO', Datacode.LOW.value, 'FT')
self.assertEqual(type(s), float, 'test_TY_equity LOW {}'.format(s))
s = financials.getRealtime('6503:TYO', 'LOW', 'FT')
self.assertEqual(float, type(s), 'test_TY_equity LOW {}'.format(s))
s = financials.getRealtime('6503:TYO', Datacode.HIGH.value, 'FT')
self.assertEqual(type(s), float, 'test_TY_equity HIGH {}'.format(s))
s = financials.getRealtime('6503:TYO', 'HIGH', 'FT')
self.assertEqual(float, type(s), 'test_TY_equity HIGH {}'.format(s))
s = financials.getRealtime('6503:TYO', Datacode.LOW_52_WEEK.value, 'FT')
self.assertEqual(type(s), float, 'test_TY_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('6503:TYO', 'LOW_52_WEEK', 'FT')
self.assertEqual(float, type(s), 'test_TY_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('6503:TYO', Datacode.HIGH_52_WEEK.value, 'FT')
self.assertEqual(type(s), float, 'test_TY_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('6503:TYO', 'HIGH_52_WEEK', 'FT')
self.assertEqual(float, type(s), 'test_TY_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('6503:TYO', Datacode.MARKET_CAP.value, 'FT')
self.assertEqual(type(s), float, 'test_TY_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('6503:TYO', 'MARKET_CAP', 'FT')
self.assertEqual(float, type(s), 'test_TY_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('6503:TYO', Datacode.VOLUME.value, 'FT')
self.assertEqual(type(s), float, 'test_TY_equity VOLUME {}'.format(s))
s = financials.getRealtime('6503:TYO', 'VOLUME', 'FT')
self.assertEqual(float, type(s), 'test_TY_equity VOLUME {}'.format(s))
s = financials.getRealtime('6503:TYO', Datacode.CURRENCY.value, 'FT')
self.assertEqual(s, 'JPY', 'test_TY_equity CURRENCY')
s = financials.getRealtime('6503:TYO', 'CURRENCY', 'FT')
self.assertEqual('JPY', s, 'test_TY_equity CURRENCY')
s = financials.getRealtime('6503:TYO', 'SECTOR', 'FT')
self.assertEqual(str, type(s), 'test_TY_equity SECTOR {}'.format(s))
self.assertEqual('Industrials', s, 'test_TY_equity SECTOR {}'.format(s))
s = financials.getRealtime('6503:TYO', 'INDUSTRY', 'FT')
self.assertEqual(str, type(s), 'test_TY_equity INDUSTRY {}'.format(s))
self.assertEqual('General Industrials', s, 'test_TY_equity INDUSTRY {}'.format(s))
def test_index(self):
s = financials.getRealtime('INX:IOM', Datacode.TICKER.value, 'FT')
self.assertEqual(s, "INX:IOM", 'test_index TICKER {}'.format(s))
s = financials.getRealtime('INX:IOM', 'ticker', 'FT')
self.assertEqual('INX:IOM', s, 'test_index TICKER {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.TICKER.value, 'FT')
self.assertEqual(s, "DAXX:GER", 'test_index TICKER {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'ticker', 'FT')
self.assertEqual('DAXX:GER', s, 'test_index TICKER {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_index LAST_PRICE {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'last_price', 'FT')
self.assertEqual(float, type(s), 'test_index LAST_PRICE {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.VOLUME.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity VOLUME {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'volume', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity VOLUME {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.LOW_52_WEEK.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'low_52_week', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.HIGH_52_WEEK.value, 'FT')
self.assertEqual(type(s), float, 'test_realtime_DE_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'high_52_week', 'FT')
self.assertEqual(float, type(s), 'test_DE_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.OPEN.value, 'FT')
self.assertIsNone(s, 'test_realtime_DE_equity OPEN {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'open', 'FT')
self.assertIsNone(s, 'test_DE_equity OPEN {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.HIGH.value, 'FT')
self.assertIsNone(s, 'test_realtime_DE_equity HIGH {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'high', 'FT')
self.assertIsNone(s, 'test_DE_equity HIGH {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.LOW.value, 'FT')
self.assertIsNone(s, 'test_realtime_DE_equity LOW {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'low', 'FT')
self.assertIsNone(s, 'test_DE_equity LOW {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.PREV_CLOSE.value, 'FT')
self.assertIsNone(s, 'test_realtime_DE_equity PREV_CLOSE {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'prev_close', 'FT')
self.assertIsNone(s, 'test_DE_equity PREV_CLOSE {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.MARKET_CAP.value, 'FT')
self.assertIsNone(s, 'test_realtime_DE_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'market_cap', 'FT')
self.assertIsNone(s, 'test_DE_equity MARKET_CAP {}'.format(s))
def test_errors(self):
s = financials.getRealtime('NO_NAME', Datacode.LAST_PRICE.value, 'FT')
self.assertIsNone(s, 'test_realtime_errors LAST_PRICE {}'.format(s))
s = financials.getRealtime('NO_NAME', 'LAST_PRICE', 'FT')
self.assertIsNone(s, 'test_errors LAST_PRICE {}'.format(s))
s = financials.getRealtime('DAXX:GER', 'Foo', 'FT')
self.assertEqual('Datacode is invalid', s, 'test_errors')
if __name__ == '__main__':
+40 -40
View File
@@ -28,7 +28,7 @@ class Test(unittest.TestCase):
def test_UK_equity(self):
s = financials.getRealtime('LON:VOD', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_UK_equity LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_UK_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('LON:VOD', Datacode.TICKER.value, 'GOOGLE')
self.assertEqual(s, 'VOD', 'test_UK_equity TICKER')
@@ -40,21 +40,21 @@ class Test(unittest.TestCase):
self.assertEqual(s, 'LON', 'test_UK_equity EXCHANGE')
s = financials.getRealtime('LON:VOD', Datacode.PREV_CLOSE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_UK_equity PREV_CLOSE {}'.format(s))
self.assertEqual(float, type(s), 'test_UK_equity PREV_CLOSE {}'.format(s))
# MARKET_CAP missing for UK stock but available for German stock - weekend issue (FX) ?
s = financials.getRealtime('LON:VOD', Datacode.MARKET_CAP.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_UK_equity MARKET_CAP {}'.format(s))
self.assertEqual(float, type(s), 'test_UK_equity MARKET_CAP {}'.format(s))
def test_UK_ETF(self):
s = financials.getRealtime('LON:CSP1', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_UK_ETF LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_UK_ETF LAST_PRICE {}'.format(s))
s = financials.getRealtime('LON:CSP1', Datacode.CURRENCY.value, 'GOOGLE')
self.assertEqual(s, 'GBX', 'test_UK_ETF CURRENCY')
s = financials.getRealtime('LON:FTAL', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_UK_ETF LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_UK_ETF LAST_PRICE {}'.format(s))
s = financials.getRealtime('LON:FTAL', Datacode.CURRENCY.value, 'GOOGLE')
self.assertEqual(s, 'GBP', 'test_UK_ETF CURRENCY')
@@ -64,10 +64,10 @@ class Test(unittest.TestCase):
def test_DE_equity(self):
s = financials.getRealtime('FRA:SAP', 7, 'GOOGLE')
self.assertEqual(type(s), float, 'test_DE_equity 7')
self.assertEqual(float, type(s), 'test_DE_equity 7')
s = financials.getRealtime('FRA:SAP', '7', 'GOOGLE')
self.assertEqual(type(s), float, 'test_DE_equity \'7\'')
self.assertEqual(float, type(s), 'test_DE_equity \'7\'')
s = financials.getRealtime('FRA:SAP', 8, 'GOOGLE')
self.assertEqual(type(s), str, 'test_DE_equity 8')
@@ -82,10 +82,10 @@ class Test(unittest.TestCase):
self.assertEqual(type(s), str, 'test_DE_equity 10')
s = financials.getRealtime('FRA:SAP', '11', 'GOOGLE')
self.assertEqual(type(s), float, 'test_DE_equity \'11\'')
self.assertEqual(float, type(s), 'test_DE_equity \'11\'')
s = financials.getRealtime('FRA:SAP', '21', 'GOOGLE')
self.assertEqual(type(s), float, 'test_DE_equity \'21\'')
self.assertEqual(float, type(s), 'test_DE_equity \'21\'')
s = financials.getRealtime('FRA:SAP', Datacode.TIMEZONE.value, 'GOOGLE')
# self.assertEqual(s, 'Europe/Berlin', 'test_DE_equity TIMEZONE')
@@ -93,51 +93,51 @@ class Test(unittest.TestCase):
def test_DE_ETF(self):
s = financials.getRealtime('FRA:C060', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_DE_ETF LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_DE_ETF LAST_PRICE {}'.format(s))
s = financials.getRealtime('FRA:C060', Datacode.CURRENCY.value, 'GOOGLE')
self.assertEqual(s, 'EUR', 'test_DE_ETF CURRENCY')
self.assertEqual('EUR', s, 'test_DE_ETF CURRENCY')
s = financials.getRealtime('FRA:C060', Datacode.TICKER.value, 'GOOGLE')
self.assertEqual(s, 'C060', 'test_DE_ETF TICKER')
self.assertEqual('C060', s, 'test_DE_ETF TICKER')
s = financials.getRealtime('FRA:C060', Datacode.EXCHANGE.value, 'GOOGLE')
self.assertEqual(s, 'FRA', 'test_DE_ETF EXCHANGE')
self.assertEqual('FRA', s, 'test_DE_ETF EXCHANGE')
s = financials.getRealtime('FRA:C060', Datacode.CURRENCY.value, 'GOOGLE')
self.assertEqual(s, 'EUR', 'test_DE_ETF CURRENCY')
self.assertEqual('EUR', s, 'test_DE_ETF CURRENCY')
s = financials.getRealtime('FRA:C060', Datacode.MARKET_CAP.value, 'GOOGLE')
self.assertIsNone(s, 'test_DE_ETF MARKET_CAP {}'.format(s))
def test_TY_equity(self):
s = financials.getRealtime('TYO:6503', Datacode.OPEN.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_TY_equity OPEN {}'.format(s))
self.assertEqual(float, type(s), 'test_TY_equity OPEN {}'.format(s))
s = financials.getRealtime('TYO:6503', Datacode.LOW.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_TY_equity LOW {}'.format(s))
self.assertEqual(float, type(s), 'test_TY_equity LOW {}'.format(s))
s = financials.getRealtime('TYO:6503', Datacode.HIGH.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_TY_equity HIGH {}'.format(s))
self.assertEqual(float, type(s), 'test_TY_equity HIGH {}'.format(s))
s = financials.getRealtime('TYO:6503', Datacode.LOW_52_WEEK.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_TY_equity LOW_52_WEEK {}'.format(s))
self.assertEqual(float, type(s), 'test_TY_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('TYO:6503', Datacode.HIGH_52_WEEK.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_TY_equity HIGH_52_WEEK {}'.format(s))
self.assertEqual(float, type(s), 'test_TY_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('TYO:6503', Datacode.MARKET_CAP.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_TY_equity MARKET_CAP {}'.format(s))
self.assertEqual(float, type(s), 'test_TY_equity MARKET_CAP {}'.format(s))
# s = financials.getRealtime('TYO:6503', Datacode.VOLUME.value, 'GOOGLE')
# self.assertEqual(type(s), float, 'test_TY_equity VOLUME {}'.format(s))
# self.assertEqual(float, type(s), 'test_TY_equity VOLUME {}'.format(s))
s = financials.getRealtime('TYO:6503', Datacode.CURRENCY.value, 'GOOGLE')
self.assertEqual(s, 'JPY', 'test_TY_equity CURRENCY')
def test_US_equity(self):
s = financials.getRealtime(' NASDAQ : AAPL ', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_equity LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_US_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime(' NASDAQ : AAPL ', Datacode.TICKER.value, 'GOOGLE')
self.assertEqual(s, 'AAPL', 'test_US_equity TICKER')
@@ -149,7 +149,7 @@ class Test(unittest.TestCase):
self.assertEqual(s, 'USD', 'test_US_equity CURRENCY')
s = financials.getRealtime('NYSE:IBM', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_equity LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_US_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('NYSE:IBM', Datacode.TICKER.value, 'GOOGLE')
self.assertEqual(s, 'IBM', 'test_US_equity TICKER')
@@ -165,34 +165,34 @@ class Test(unittest.TestCase):
self.assertEqual(s, 'IBM Common Stock', 'test_US_equity NAME')
s = financials.getRealtime('NYSE:IBM', Datacode.LOW.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_equity LOW {}'.format(s))
self.assertEqual(float, type(s), 'test_US_equity LOW {}'.format(s))
s = financials.getRealtime('NYSE:IBM', Datacode.HIGH.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_equity HIGH {}'.format(s))
self.assertEqual(float, type(s), 'test_US_equity HIGH {}'.format(s))
s = financials.getRealtime('NYSE:IBM', Datacode.LOW_52_WEEK.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_equity LOW_52_WEEK {}'.format(s))
self.assertEqual(float, type(s), 'test_US_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('NYSE:IBM', Datacode.HIGH_52_WEEK.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_equity HIGH_52_WEEK {}'.format(s))
self.assertEqual(float, type(s), 'test_US_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('NYSE:IBM', Datacode.MARKET_CAP.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_equity MARKET_CAP {}'.format(s))
self.assertEqual(float, type(s), 'test_US_equity MARKET_CAP {}'.format(s))
# s = financials.getRealtime('NYSE:IBM', Datacode.VOLUME.value, 'GOOGLE')
# self.assertEqual(type(s), float, 'test_US_equity VOLUME {}'.format(s))
# self.assertEqual(float, type(s), 'test_US_equity VOLUME {}'.format(s))
s = financials.getRealtime('NYSE:IBM', Datacode.TIMESTAMP.value, 'GOOGLE')
self.assertEqual(s, 'Data doesn\'t exist - 999', 'test_US_equity TIMESTAMP')
s = financials.getRealtime('NYSE:IBM', Datacode.TIMEZONE.value, 'GOOGLE')
# self.assertEqual(s, 'America/New_York', 'test_US_equity TIMEZONE')
self.assertEqual(s, 'GMT-4', 'test_US_equity TIMEZONE')
# self.assertEqual(s, 'GMT-5', 'test_US_equity TIMEZONE')
# self.assertEqual('America/New_York', s, 'test_US_equity TIMEZONE')
self.assertEqual('GMT-4', s, 'test_US_equity TIMEZONE')
# self.assertEqual('GMT-5', s, 'test_US_equity TIMEZONE')
def test_US_mutuals(self):
s = financials.getRealtime('MUTF:VFIAX', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_US_mutuals LAST_PRICE - {}'.format(s))
self.assertEqual(float, type(s), 'test_US_mutuals LAST_PRICE - {}'.format(s))
s = financials.getRealtime('MUTF:VFIAX', Datacode.CURRENCY.value, 'GOOGLE')
self.assertEqual(s, 'USD', 'test_US_mutuals CURRENCY')
@@ -202,22 +202,22 @@ class Test(unittest.TestCase):
def test_index(self):
s = financials.getRealtime('INDEXDB:DAX', Datacode.LAST_PRICE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_index LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_index LAST_PRICE {}'.format(s))
s = financials.getRealtime('INDEXDB:DAX', Datacode.CHANGE_IN_PERCENT.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_index CHANGE_IN_PERCENT')
self.assertEqual(float, type(s), 'test_index CHANGE_IN_PERCENT')
s = financials.getRealtime('INDEXDB:DAX', Datacode.CHANGE.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_index CHANGE')
self.assertEqual(float, type(s), 'test_index CHANGE')
s = financials.getRealtime('INDEXDB:DAX', Datacode.OPEN.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_index OPEN')
self.assertEqual(float, type(s), 'test_index OPEN')
s = financials.getRealtime('INDEXDB:DAX', Datacode.LOW.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_index LOW')
self.assertEqual(float, type(s), 'test_index LOW')
s = financials.getRealtime('INDEXDB:DAX', Datacode.HIGH.value, 'GOOGLE')
self.assertEqual(type(s), float, 'test_index HIGH')
self.assertEqual(float, type(s), 'test_index HIGH')
def test_errors(self):
s = financials.getRealtime(None, Datacode.LAST_PRICE.value, 'GOOGLE')
@@ -230,7 +230,7 @@ class Test(unittest.TestCase):
self.assertIsNone(s, 'test_errors')
s = financials.getRealtime('NYS:IBM', 'Foo', 'GOOGLE')
self.assertEqual(s, 'Datacode is not a number', 'test_errors')
self.assertEqual(s, 'Datacode is invalid', 'test_errors')
# Historic data not supported on GOOGLE
+102 -30
View File
@@ -16,6 +16,7 @@ import unittest
import financials
from datacode import Datacode
import testutils
financials = financials.createInstance(None)
@@ -26,111 +27,182 @@ class Test(unittest.TestCase):
def test_currency(self):
s = financials.getRealtime('EURGBP=X', Datacode.CURRENCY.value, 'YAHOO')
self.assertEqual(type(s), str, 'test_currency CURRENCY')
self.assertEqual(str, type(s), 'test_currency CURRENCY')
s = financials.getRealtime('EURGBP=X', Datacode.LAST_PRICE.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_currency LAST_PRICE')
self.assertEqual(float, type(s), 'test_currency LAST_PRICE')
def test_realtime_US_equity(self):
s = financials.getRealtime('^GSPC', Datacode.NAME.value, 'YAHOO')
self.assertEqual(type(s), str, 'test_realtime_US_equity NAME {}'.format(s))
self.assertEqual(str, type(s), 'test_realtime_US_equity NAME {}'.format(s))
self.assertIn('500', s, 'test_realtime_US_equity NAME {}'.format(s))
s = financials.getRealtime('IBM', Datacode.PREV_CLOSE.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity PREV_CLOSE {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity PREV_CLOSE {}'.format(s))
s = financials.getRealtime('IBM', Datacode.OPEN.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity OPEN {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity OPEN {}'.format(s))
s = financials.getRealtime('IBM', Datacode.LAST_PRICE.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('IBM', Datacode.LOW.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity LOW {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity LOW {}'.format(s))
s = financials.getRealtime('IBM', Datacode.HIGH.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity HIGH {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity HIGH {}'.format(s))
s = financials.getRealtime('IBM', Datacode.HIGH_52_WEEK.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity HIGH_52_WEEK {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('IBM', Datacode.LOW_52_WEEK.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity LOW_52_WEEK {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('IBM', Datacode.MARKET_CAP.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity MARKET_CAP {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('IBM', Datacode.VOLUME.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity VOLUME {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_equity VOLUME {}'.format(s))
s = financials.getRealtime('IBM', Datacode.AVG_DAILY_VOL_3MOMTH.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_equity AVG_DAILY_VOL_3MOMTH {}'.format(s))
s = financials.getRealtime('IBM', Datacode.AVG_DAILY_VOL_3MONTH.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_realtime_US_equity AVG_DAILY_VOL_3MONTH {}'.format(s))
s = financials.getRealtime('IBM', Datacode.NAME.value, 'YAHOO')
self.assertEqual(type(s), str, 'test_realtime_US_equity NAME {}'.format(s))
self.assertEqual(str, type(s), 'test_realtime_US_equity NAME {}'.format(s))
self.assertEqual(s, 'International Business Machines Corporation',
'test_realtime_US_equity NAME {}'.format(s))
s = financials.getRealtime('IBM', Datacode.SECTOR.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_realtime_US_equity SECTOR {}'.format(s))
self.assertEqual(s, 'Technology', 'test_realtime_US_equity SECTOR {}'.format(s))
s = financials.getRealtime('IBM', Datacode.INDUSTRY.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_realtime_US_equity INDUSTRY {}'.format(s))
self.assertEqual(s, 'Information Technology Services', 'test_realtime_US_equity INDUSTRY {}'.format(s))
s = financials.getRealtime('IBM', Datacode.TIMEZONE.value, 'YAHOO')
self.assertEqual(s, 'America/New_York', 'test_realtime_US_equity TIMEZONE {}'.format(s))
s = financials.getRealtime('IBM', Datacode.BETA.value, 'YAHOO')
self.assertTrue(testutils.is_positive_float(s), 'test_realtime_US_equity BETA {}'.format(s))
s = financials.getRealtime('IBM', Datacode.EPS.value, 'YAHOO')
self.assertTrue(testutils.is_positive_float(s), 'test_realtime_US_equity EPS {}'.format(s))
s = financials.getRealtime('IBM', Datacode.PE_RATIO.value, 'YAHOO')
self.assertTrue(testutils.is_positive_float(s), 'test_realtime_US_equity PE_RATIO {}'.format(s))
s = financials.getRealtime('IBM', Datacode.DIV.value, 'YAHOO')
self.assertTrue(testutils.is_positive_float(s), 'test_realtime_US_equity DIV {}'.format(s))
s = financials.getRealtime('IBM', Datacode.DIV_YIELD.value, 'YAHOO')
self.assertTrue(testutils.is_positive_float(s), 'test_realtime_US_equity DIV_YIELD {}'.format(s))
s = financials.getRealtime('IBM', Datacode.EX_DIV_DATE.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_realtime_US_equity EX_DIV_DATE {}'.format(s))
self.assertTrue(testutils.is_date(s), 'test_realtime_US_equity EX_DIV_DATE {}'.format(s))
s = financials.getRealtime('IBM', Datacode.PAYOUT_RATIO.value, 'YAHOO')
self.assertTrue(testutils.is_positive_float(s), 'test_realtime_US_equity PAYOUT_RATIO {}'.format(s))
def test_realtime_US_mutuals(self):
s = financials.getRealtime('VGSLX', Datacode.LAST_PRICE.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_mutuals LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_mutuals LAST_PRICE {}'.format(s))
s = financials.getRealtime('VFIAX', Datacode.LAST_PRICE.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_US_mutuals LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_US_mutuals LAST_PRICE {}'.format(s))
s = financials.getRealtime('VFIAX', Datacode.LAST_PRICE_DATE.value, 'YAHOO')
self.assertEqual(type(s), str, 'test_realtime_US_mutuals LAST_PRICE_DATE {}'.format(s))
self.assertEqual(str, type(s), 'test_realtime_US_mutuals LAST_PRICE_DATE {}'.format(s))
s = financials.getRealtime('VFIAX', Datacode.LAST_PRICE_TIME.value, 'YAHOO')
self.assertEqual(type(s), str, 'test_realtime_US_mutuals LAST_PRICE_TIME {}'.format(s))
self.assertEqual(str, type(s), 'test_realtime_US_mutuals LAST_PRICE_TIME {}'.format(s))
def test_realtime_UK_ETF(self):
s = financials.getRealtime('VERX.L', Datacode.LAST_PRICE.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_UK_ETF LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_UK_ETF LAST_PRICE {}'.format(s))
s = financials.getRealtime('VERX.L', Datacode.TIMEZONE.value, 'YAHOO')
self.assertEqual(s, 'Europe/London', 'test_realtime_UK_ETF TIMEZONE {}'.format(s))
s = financials.getRealtime('CSP1.L', Datacode.NAME.value, 'YAHOO')
self.assertEqual(type(s), str, 'test_realtime_UK_ETF NAME {}'.format(s))
self.assertEqual(str, type(s), 'test_realtime_UK_ETF NAME {}'.format(s))
self.assertEqual(s, 'iShares VII Public Limited Company - iShares Core S&P 500 UCITS ETF',
'test_realtime_UK_ETF NAME {}'.format(s))
s = financials.getRealtime('C060.DE', Datacode.NAME.value, 'YAHOO')
self.assertEqual(type(s), str, 't_realtime_UK_ETF NAME {}'.format(s))
self.assertEqual(str, type(s), 't_realtime_UK_ETF NAME {}'.format(s))
def test_realtime_DE_equity(self):
s = financials.getRealtime('SAP.DE', Datacode.LAST_PRICE.value, 'YAHOO')
self.assertEqual(type(s), float, 'test_realtime_DE_equity LAST_PRICE {}'.format(s))
self.assertEqual(float, type(s), 'test_realtime_DE_equity LAST_PRICE {}'.format(s))
s = financials.getRealtime('SAP.DE', Datacode.TIMEZONE.value, 'YAHOO')
self.assertEqual(s, 'Europe/Berlin', 'test_realtime_DE_equity TIMEZONE {}'.format(s))
s = financials.getRealtime('SAP.DE', Datacode.SECTOR.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_realtime_DE_equity SECTOR {}'.format(s))
self.assertEqual(s, 'Technology', 'test_realtime_DE_equity SECTOR {}'.format(s))
s = financials.getRealtime('SAP.DE', Datacode.INDUSTRY.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_realtime_DE_equity INDUSTRY {}'.format(s))
self.assertEqual(s, 'Software—Application', 'test_realtime_DE_equity INDUSTRY {}'.format(s))
def test_TY_equity(self):
s = financials.getRealtime('6503.T', Datacode.OPEN.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_TY_equity OPEN {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.LOW.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_TY_equity LOW {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.HIGH.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_TY_equity HIGH {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.LOW_52_WEEK.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_TY_equity LOW_52_WEEK {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.HIGH_52_WEEK.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_TY_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.MARKET_CAP.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_TY_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.VOLUME.value, 'YAHOO')
self.assertEqual(float, type(s), 'test_TY_equity VOLUME {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.CURRENCY.value, 'YAHOO')
self.assertEqual(s, 'JPY', 'test_TY_equity CURRENCY')
s = financials.getRealtime('6503.T', Datacode.SECTOR.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_TY_equity SECTOR {}'.format(s))
self.assertEqual(s, 'Industrials', 'test_TY_equity SECTOR {}'.format(s))
s = financials.getRealtime('6503.T', Datacode.INDUSTRY.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_TY_equity INDUSTRY {}'.format(s))
self.assertEqual(s, 'Electrical Equipment & Parts', 'test_TY_equity INDUSTRY {}'.format(s))
def test_historic_US_equity(self):
s = financials.getHistoric('IBM', Datacode.LAST_PRICE.value, '2017-01-01', 'YAHOO')
self.assertEqual(s, 'Not a trading day \'2017-01-01\'', 'test_historic_US_equity LAST_PRICE {}'.format(s))
self.assertEqual('Not a trading day \'2017-01-01\'', s, 'test_historic_US_equity LAST_PRICE {}'.format(s))
s = financials.getHistoric('IBM', Datacode.CLOSE.value, '2017-01-01', 'YAHOO')
self.assertEqual(s, 'Not a trading day \'2017-01-01\'', 'test_historic_US_equity CLOSE {}'.format(s))
self.assertEqual('Not a trading day \'2017-01-01\'', s, 'test_historic_US_equity CLOSE {}'.format(s))
s = financials.getHistoric('IBM', Datacode.LAST_PRICE.value, '2017-01-03', 'YAHOO')
self.assertEqual(s, 'Data doesn\'t exist - 21', 'test_historic_US_equity LAST_PRICE {}'.format(s))
self.assertEqual('Data doesn\'t exist - 21', s, 'test_historic_US_equity LAST_PRICE {}'.format(s))
s = financials.getHistoric('IBM', Datacode.CLOSE.value, '2017-01-03', 'YAHOO')
self.assertEqual(s, 167.190002, 'test_historic_US_equity CLOSE {}'.format(s))
self.assertEqual(167.190002, s, 'test_historic_US_equity CLOSE {}'.format(s))
financials.yahoo.historicdata = {}
s = financials.getHistoric('IBM', Datacode.CLOSE.value, '2017-01-03', 'YAHOO')
self.assertEqual(s, 167.190002, 'test_historic_US_equity CLOSE {}'.format(s))
self.assertEqual(167.190002, s, 'test_historic_US_equity CLOSE {}'.format(s))
directory = os.path.join(str(pathlib.Path.home()), '.financials-extension')
ibm = os.path.join(directory, 'yahoo-IBM.csv')
@@ -142,11 +214,11 @@ class Test(unittest.TestCase):
financials.yahoo.historicdata = {}
s = financials.getHistoric('IBM', Datacode.CLOSE.value, '2017-01-03', 'YAHOO')
self.assertEqual(s, 167.190002, 'test_historic_US_equity CLOSE {}'.format(s))
self.assertEqual(167.190002, s, 'test_historic_US_equity CLOSE {}'.format(s))
# Note: quarterly dividend and splits will change past adjusted prices - will fail after the next dividend
s = financials.getHistoric('IBM', Datacode.ADJ_CLOSE.value, '2017-01-03', 'YAHOO')
self.assertEqual(s, 145.416626, 'test_historic_US_equity ADJ_CLOSE {}'.format(s))
self.assertEqual(141.637695, s, 'test_historic_US_equity ADJ_CLOSE {}'.format(s))
def test_historic_UK_ETF(self):
+10
View File
@@ -0,0 +1,10 @@
import re
def is_positive_float(f):
return type(f) == float and f > 0.0
def is_date(s):
match = re.compile(r'^20\d\d-\d\d-\d\d$', flags=re.DOTALL).search(s)
return match is not None
+29 -6
View File
@@ -40,6 +40,15 @@ def raw(m, key, default=0.0):
return default
def fmt(m, key, default=0.0):
try:
return m[key]['fmt']
except:
pass
return default
class Yahoo(BaseClient):
def __init__(self, ctx):
super().__init__()
@@ -103,7 +112,7 @@ class Yahoo(BaseClient):
cookies = [cookiejar.Cookie(version=0,
name="B",
value="9898htldgiar5&b=3&s=gt",
value="7pbfivtfkl00m&b=3&s=if",
port=None, port_specified=None,
domain=".yahoo.com", domain_specified=True, domain_initial_dot=True,
path="/", path_specified=True,
@@ -154,6 +163,10 @@ class Yahoo(BaseClient):
logger.error(traceback.format_exc())
return 'Yahoo.getRealtime({}, {}) - parsing: {}'.format(ticker, datacode, e)
with open(os.path.join(self.basedir, 'yahoo-{}.js'.format(ticker)), "w") as text_file:
print(f"// '{url}' QuoteSummaryStore:\n", file=text_file)
pprint.pprint(results.asList(), stream=text_file)
try:
price = results['price']
quoteType = results['quoteType']
@@ -177,12 +190,22 @@ class Yahoo(BaseClient):
tick[Datacode.HIGH] = float(raw(price, 'regularMarketDayHigh'))
tick[Datacode.LAST_PRICE] = float(raw(price, 'regularMarketPrice'))
tick[Datacode.VOLUME] = float(raw(price, 'regularMarketVolume'))
tick[Datacode.AVG_DAILY_VOL_3MOMTH] = float(raw(price, 'averageDailyVolume3Month'))
tick[Datacode.AVG_DAILY_VOL_3MONTH] = float(raw(price, 'averageDailyVolume3Month'))
tick[Datacode.BETA] = float(raw(summaryDetail, 'beta'))
tick[Datacode.EPS] = self.save_wrapper(lambda: float(raw(results['defaultKeyStatistics'], 'trailingEps')))
tick[Datacode.PE_RATIO] = float(raw(summaryDetail, 'trailingPE'))
tick[Datacode.DIV] = float(raw(summaryDetail, 'dividendRate'))
tick[Datacode.DIV_YIELD] = float(raw(summaryDetail, 'dividendYield'))
tick[Datacode.EX_DIV_DATE] = self.save_wrapper(lambda: dateutil.parser.parse(str(fmt(summaryDetail, 'exDividendDate'))).date())
tick[Datacode.PAYOUT_RATIO] = float(raw(summaryDetail, 'payoutRatio'))
tick[Datacode.LOW_52_WEEK] = float(raw(summaryDetail, 'fiftyTwoWeekLow'))
tick[Datacode.HIGH_52_WEEK] = float(raw(summaryDetail, 'fiftyTwoWeekHigh'))
tick[Datacode.MARKET_CAP] = float(raw(summaryDetail, 'marketCap'))
tick[Datacode.TIMEZONE] = None
tick[Datacode.LAST_PRICE_DATE] = None
tick[Datacode.LAST_PRICE_TIME] = None
if quoteType:
t = int(price['regularMarketTime'])
tz = pytz.timezone(quoteType['exchangeTimezoneName'])
@@ -204,12 +227,12 @@ class Yahoo(BaseClient):
tick[Datacode.NAME] = tick[Datacode.TICKER]
except BaseException as e:
with open(os.path.join(self.basedir, 'yahoo-{}.js'.format(ticker)), "w") as text_file:
pprint.pprint(f"// '{url}'\r\n\r\n{results.asList()}", stream=text_file)
logger.error(traceback.format_exc())
return 'Yahoo.getRealtime({}, {}) - process: {}'.format(ticker, datacode, e)
tick[Datacode.SECTOR] = self.save_wrapper(lambda: str(results['summaryProfile']['sector']))
tick[Datacode.INDUSTRY] = self.save_wrapper(lambda: str(results['summaryProfile']['industry']))
return self._return_value(self.realtime[ticker], datacode)
def getHistoric(self, ticker: str, datacode: int, date):