Compare commits

...
15 Commits
16 changed files with 686 additions and 341 deletions
Binary file not shown.
+94 -19
View File
@@ -1,55 +1,128 @@
# Financials-Extension
Extension for LibreOffice Calc to make stock market, index and FX data available in a Calc spread
sheet - currently supports Yahoo's, Financial Times' and Google's (without FX data) finance web sites using web scraping.
This is a Python based extension for LibreOffice Calc to make stock market, index and FX data available in Calc
spreadsheets - currently supporting Yahoo's, Financial Times' and Google's (without FX data) finance websites
using old-fashioned web scraping.
### System dependencies:
### Feedback requested:
Requires the following Python 3 (used by LibreOffice) packages (on top of standard libs): dateutil, pytz, pyparsing
Please provide feedback about using the extension here: https://github.com/cmallwitz/Financials-Extension/issues/10
The following steps have worked for me on a fresh Debian installation (as root)
### System requirements:
This extension requires the following Python 3 packages (on top of standard libs): dateutil, pytz, pyparsing. These are
from within LibreOffice, so if your LibreOffice comes with it's own Python runtime (e.g. Windows) they need to be
installed there instead somewhere else in the system.
On Ubuntu 18 and 20, dateutil and pytz may already be installed, but you can get all you need by running
- sudo apt-get install python3-dateutil python3-tz python3-pyparsing
On Debian 10, the following steps have worked for me (as root)
- apt install python3-pip
- pip3 install python-dateutil
- pip3 install pytz
- pip3 install pyparsing
- pip3 install python-dateutil pytz pyparsing
Users on Windows 10 have reported this to work - as LibreOffice on Windows ships with its own, but minimal
Python runtime a few more steps are required
- Download the script https://bootstrap.pypa.io/get-pip.py to your computer
- Start a Command Prompt (CMD) as Administrator
- on this command prompt run (change path as required)
"c:\Program Files\LibreOffice\program\python.exe" c:\temp\get-pip.py
- and then
"c:\Program Files\LibreOffice\program\python.exe" -m pip install python-dateutil pytz pyparsing
### Usage:
Have a look at the 'releases' tab above: download a prebuild **Financials-Extension.oxt** file and load it into Calc
Under 'Releases' on GitHub there is downloadable **Financials-Extension.oxt** file - load it into Calc
under menu item: Tools, Extension Manager...
Getting data should be a simple as having this in a cell:
- `=GETREALTIME("IBM",21,"YAHOO")`
- `=GETREALTIME("NYSE:IBM",21,"GOOGLE")`
- `=GETREALTIME("IBM:NYQ",21,"FT")`
- `=GETHISTORIC("IBM",90,"2020-12-01","YAHOO")`
Codes 21 and 90 stand for "last price" and "close" (see below), respectively.
Only Yahoo has historic data available.
There is a file **examples.ods** there too with usage examples and possible arguments to functions.
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
You have to check the respective websites to work out what symbol is the right one for you. If a website 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 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.
### LibreOffice: using , (comma) vs ; (semicolon) to separate arguments in formula
There is a setting in "Tools" / "Options..." / "LibreOffice Calc" / "Formula" called "Functions". Here the user can specify the character used to separate arguments in formula.
Mine is set to , (comma) - when I enter ; (semicolon) in a formula (Ubuntu / UK English), no error is reported but the semicolon is converted to , (comma)
Depending on your system's language and default LibreOffice settings, you maybe better off using ; instead of , in your formulas.
### 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|Code|YAHOO|FT|GOOGLE|YAHOO (historic)|
| :--- | :--- | :---: | :---: | :---: | :---: |
|PREV_CLOSE|5|Yes|Yes|Yes||
|OPEN|6|Yes|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|Yes|
|HIGH|16|Yes|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|Yes|
|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|No|No|No|Yes|
|ADJ_CLOSE|91|No|No|No|Yes|
|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:
First of all, a hint for using LibreCalc: if you want to refresh data you can press SHIFT-CTRL-F9 - this will force a
A hint for using LibreCalc: if you want to refresh data you can press SHIFT-CTRL-F9 - this will force a
recalculation of all formulas in all sheets.
Secondly the extension saves some debug information under your user directory in a directory ".financials-extension":
the HTML for each stock symbol is saved in a separate file (depending on source and ticker symbol). You can open it
the HTML for each stock symbol is saved in a separate file (depending on the source and ticker symbol). You can open it
your favorite web browser (or other tools) to check if the page actually contained the information you are looking for.
If it does the file trace.log has a record of all calls to the extension and the value returned to LibreOffice.
If it does, the file trace.log has a record of all calls to the extension with the value returned to LibreOffice.
Otherwise, the file extension.log in the same location might have more details about errors or exceptions.
### Build:
You will need the LibreOffice SDK installed.
On my system I installed packages: libreoffice-dev libreoffice-java-common libreoffice-script-provider-python
On my system (Ubuntu) I installed packages: libreoffice-dev libreoffice-java-common libreoffice-script-provider-python
\# depending on your location...
cd ~/tech/IdeaProjects/Financials-Extension/
python3 src/test_yahoo.py
python3 src/test_google.py
python3 -m unittest discover src
\# This builds file **Financials-Extension.oxt**
@@ -57,8 +130,10 @@ python3 src/test_google.py
### Tested with:
- Debian 10.3 / LibreOffice Calc 6.1.5.2 / Python 3.7.3
- Ubuntu 20.10 / LibreOffice Calc 7.0.3.1 / Python 3.8.6
- 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.5 / LibreOffice Calc 6 / Python 3.6.9
- Ubuntu 18.04 / LibreOffice Calc 6 / Python 3.6.7
- Ubuntu 16.04 / LibreOffice Calc 5 (previous versions)
Binary file not shown.
+9 -4
View File
@@ -1,4 +1,9 @@
#!/bin/bash
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
set -o noclobber
export PATH=$PATH:/usr/lib/libreoffice/sdk/bin
export PATH=$PATH:/usr/lib/libreoffice/program
@@ -29,9 +34,9 @@ cp -f "${PWD}"/src/baseclient.py "${PWD}"/build/
cp -f "${PWD}"/src/jsonParser.py "${PWD}"/build/
cp -f "${PWD}"/src/naivehtmlparser.py "${PWD}"/build/
cp -f "${PWD}"/src/tz.py "${PWD}"/build/
cp -f "${PWD}"/src/ft.py "${PWD}"/build/
cp -f "${PWD}"/src/google.py "${PWD}"/build/
cp -f "${PWD}"/src/yahoo.py "${PWD}"/build/
cp -f "${PWD}"/src/financials_ft.py "${PWD}"/build/
cp -f "${PWD}"/src/financials_google.py "${PWD}"/build/
cp -f "${PWD}"/src/financials_yahoo.py "${PWD}"/build/
echo "Package into oxt file..."
pushd "${PWD}"/build/
BIN
View File
Binary file not shown.
+44 -12
View File
@@ -15,15 +15,15 @@ import os
import pathlib
import random
import select
from http.client import HTTPConnection, HTTPSConnection, HTTPException
from http import cookiejar
import urllib.request
from http import cookiejar
from http.client import HTTPConnection, HTTPSConnection, HTTPException
from datacode import Datacode
logger = logging.getLogger(__name__)
# logger.setLevel(logging.DEBUG)
@@ -48,19 +48,26 @@ class BaseClient:
os.makedirs(self.basedir, exist_ok=True)
user_agents = [
'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 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.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/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',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
]
self.default_headers = {
@@ -101,7 +108,7 @@ class BaseClient:
connection = HTTPConnection(host, **kwargs) if scheme == 'http:' else HTTPSConnection(host, **kwargs)
logger.debug('Creating request -----------------------------------------------------')
logger.info('url=%s', url)
logger.info("url='%s'", url)
self.last_url = url
@@ -158,7 +165,8 @@ class BaseClient:
scheme, _, host, path = url.split('/', 3)
location = '{}//{}{}'.format(scheme, host, location)
self.response = self.request('POST' if data else 'GET', location, data, headers, cookies, **kwargs)
self.response = self.request('POST' if data else 'GET', location, data, headers, cookies,
**kwargs)
text = self.response.read()
else:
raise RedirectException(location)
@@ -238,8 +246,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]
+9 -1
View File
@@ -29,7 +29,15 @@ 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
+45 -18
View File
@@ -8,36 +8,55 @@
# version 3 of the License, or (at your option) any later version.
import datetime
import dateutil.parser
import inspect
import locale
import logging
import os
import sys
import pathlib
import platform
import sys
import time
from functools import wraps
from importlib import util
import unohelper
from com.financials.getinfo import Financials
basedir = os.path.join(str(pathlib.Path.home()), '.financials-extension')
os.makedirs(basedir, exist_ok=True)
logging.basicConfig(
handlers=[logging.FileHandler(filename=os.path.join(basedir, 'extension.log'), encoding='utf-8', mode='a+')],
format="%(asctime)s %(name)s %(levelname)s %(message)s",
level=logging.WARN)
# Add current directory to import path
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
if current_dir not in sys.path:
sys.path.insert(0, current_dir)
dateutil_missing = util.find_spec("dateutil") is None
pyparsing_missing = util.find_spec("pyparsing") is None
pytz_missing = util.find_spec("pytz") is None
if dateutil_missing or pyparsing_missing or pytz_missing:
msg = ''
msg += ' dateutil' if dateutil_missing else ''
msg += ' pyparsing' if pyparsing_missing else ''
msg += ' pytz' if pytz_missing else ''
raise Exception("THIS EXTENSION NEEDS THE FOLLOWING PYTHON 3 LIBRARIES INSTALLED:" + msg)
import dateutil.parser
from datacode import Datacode
import google
import yahoo
import ft
import financials_google as google
import financials_yahoo as yahoo
import financials_ft as ft
from version import version
implementation_name = "com.financials.getinfo.python.FinancialsImpl" # as defined in Financials.xcu
implementation_services = ("com.sun.star.sheet.AddIn",)
basedir = os.path.join(str(pathlib.Path.home()), '.financials-extension')
os.makedirs(basedir, exist_ok=True)
def profile(fn):
@wraps(fn)
@@ -46,7 +65,7 @@ def profile(fn):
r = fn(*args, **kwargs)
elapsed = time.perf_counter() - start
with open(os.path.join(basedir, 'trace.log'), "a+") as text_file:
with open(os.path.join(basedir, 'trace.log'), "a+", encoding="utf-8") as text_file:
print(
f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')} {fn.__name__} *args={args[1:]} r='{r}' {(1000 * elapsed):.3f} ms",
file=text_file)
@@ -88,9 +107,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 +168,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)
@@ -157,7 +182,7 @@ class FinancialsImpl(unohelper.Base, Financials):
try:
offset = int(date) # offset for 1899-12-30
d = dateutil.parser.parse('1899-12-30') + datetime.timedelta(days=offset)
d = dateutil.parser.parse('1899-12-30', yearfirst=True, dayfirst=False) + datetime.timedelta(days=offset)
d = d.date().isoformat()
except:
return 'Date format not supported: {}'.format(date)
@@ -166,7 +191,7 @@ class FinancialsImpl(unohelper.Base, Financials):
elif type(date) == str:
try:
int(dateutil.parser.parse(date).strftime('%s'))
int(dateutil.parser.parse(date, yearfirst=True, dayfirst=False).timestamp())
except:
return 'Date format not supported: \'{}\''.format(date)
@@ -194,7 +219,7 @@ class FinancialsImpl(unohelper.Base, Financials):
@profile
def support(self, datacode):
s = 'ctx={}\nid(self)={}\nversion={}\nfile={}\ncwd={}\nhome={}\nuname={}\npid={}\nsys.executable={}\nsys.version={}'.format(
s = 'ctx={}\nid(self)={}\nversion={}\nfile={}\ncwd={}\nhome={}\nuname={}\npid={}\nsys.executable={}\nsys.version={}\nlocale={}\ndefaultlocale={}'.format(
self.ctx,
id(self),
version,
@@ -204,7 +229,9 @@ class FinancialsImpl(unohelper.Base, Financials):
' '.join(platform.uname()),
os.getpid(),
sys.executable,
sys.version.replace("\n", " "))
sys.version.replace("\n", " "),
locale.getlocale(),
locale.getdefaultlocale())
if datacode:
s = '{}\ntype(datacode)={}\nstr(datacode)={}'.format(
+69 -11
View File
@@ -1,4 +1,4 @@
# ft.py
# financials_ft.py
#
# license: GNU LGPL
#
@@ -7,13 +7,13 @@
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
import dateutil.parser
import html
import logging
import os
import re
import time
import traceback
import dateutil.parser
import jsonParser
from baseclient import BaseClient
@@ -21,6 +21,8 @@ from datacode import Datacode
from tz import whois_timezone_info
logger = logging.getLogger(__name__)
# logger.setLevel(logging.DEBUG)
@@ -79,11 +81,15 @@ class FT(BaseClient):
try:
text = self.urlopen(url, redirect=True, data=None, headers=None)
with open(os.path.join(self.basedir, f'ft-{ticker}.html'), "w") as text_file:
except BaseException as e:
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return f'FT.getRealtime({ticker}, {datacode}) - urlopen endpoint: {str(e)}'
try:
with open(os.path.join(self.basedir, f'ft-{ticker}.html'), "w", encoding="utf-8") as text_file:
print(f"<!-- '{self.last_url}' -->\r\n\r\n{text}", file=text_file)
except BaseException as e:
logger.error(traceback.format_exc())
return f'FT.getRealtime({ticker}, {datacode}) - urlopen endpoint: {str(e)}'
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
tick[Datacode.TIMESTAMP] = time.time()
@@ -107,10 +113,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
@@ -161,6 +174,13 @@ class FT(BaseClient):
tick[Datacode.VOLUME] = self.save_wrapper(
lambda: handle_abbreviations(html.unescape(match.group(1))))
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:
@@ -177,7 +197,7 @@ class FT(BaseClient):
try:
value = html.unescape(match.group(1)).strip()
dt = dateutil.parser.parse(value, tzinfos=whois_timezone_info)
dt = dateutil.parser.parse(value, yearfirst=True, dayfirst=False, tzinfos=whois_timezone_info)
tick[Datacode.LAST_PRICE_DATE] = dt.date()
tick[Datacode.LAST_PRICE_TIME] = dt.time()
@@ -236,17 +256,55 @@ class FT(BaseClient):
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 = 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, yearfirst=True, dayfirst=False, 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())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return f'FT.getRealtime({ticker}, {datacode}) - process: {str(e)}'
logger.info(tick)
+14 -10
View File
@@ -1,4 +1,4 @@
# google.py
# financials_google.py
#
# license: GNU LGPL
#
@@ -8,15 +8,15 @@
# version 3 of the License, or (at your option) any later version.
import dateutil
import html
import logging
import os
import re
import time
import traceback
import xml.etree.ElementTree as ET
import dateutil
from baseclient import BaseClient, RedirectException
from datacode import Datacode
from naivehtmlparser import NaiveHTMLParser
@@ -81,7 +81,7 @@ class Google(BaseClient):
except RedirectException as e:
self.location = e.location.replace('&' + q_param, '')
except BaseException as e:
logger.error(traceback.format_exc())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Google.getRealtime(\'{}\', {}) - location: {}'.format(ticker, datacode, e)
if not self.location:
@@ -91,11 +91,15 @@ class Google(BaseClient):
try:
text = self.urlopen(url)
with open(os.path.join(self.basedir, 'google-{}.html'.format(ticker)), "w") as text_file:
except BaseException as e:
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Google.getRealtime(\'{}\', {}) - urlopen: {} {}'.format(ticker, datacode, e, url)
try:
with open(os.path.join(self.basedir, 'google-{}.html'.format(ticker)), "w", encoding="utf-8") as text_file:
print(f"<!-- '{url}' -->\r\n\r\n{text}", file=text_file)
except BaseException as e:
logger.error(traceback.format_exc())
return 'Google.getRealtime(\'{}\', {}) - urlopen: {} {}'.format(ticker, datacode, e, url)
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
if ticker not in self.realtime:
self.realtime[ticker] = {}
@@ -124,7 +128,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>'
@@ -196,7 +200,7 @@ class Google(BaseClient):
try:
value = html.unescape(header.find('./div[1]/span[1]/span[2]').text).replace('·', '').strip()
logger.debug(value)
dt = dateutil.parser.parse(value, tzinfos=whois_timezone_info)
dt = dateutil.parser.parse(value, yearfirst=True, dayfirst=False, tzinfos=whois_timezone_info)
tick[Datacode.LAST_PRICE_DATE] = dt.date()
tick[Datacode.LAST_PRICE_TIME] = dt.time()
@@ -252,7 +256,7 @@ class Google(BaseClient):
logger.info(tick)
except BaseException as e:
logger.warning(traceback.format_exc())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Google.getRealtime({}, {}) - process: {}'.format(ticker, datacode, e)
return self._return_value(self.realtime[ticker], datacode)
+73 -39
View File
@@ -1,4 +1,4 @@
# yahoo.py
# financials_yahoo.py
#
# license: GNU LGPL
#
@@ -10,24 +10,25 @@
import csv
import datetime
import dateutil.parser
import html
import logging
import os
import pprint
import pytz
import re
import time
import traceback
import urllib.parse
from datacode import Datacode
from baseclient import BaseClient, HttpException
from http import cookiejar
import jsonParser
import dateutil.parser
import pytz
import jsonParser
from baseclient import BaseClient, HttpException
from datacode import Datacode
logger = logging.getLogger(__name__)
# logger.setLevel(logging.DEBUG)
@@ -40,6 +41,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__()
@@ -56,7 +66,7 @@ class Yahoo(BaseClient):
if not os.path.isfile(fn):
return
with open(fn, newline='') as csvfile:
with open(fn, newline='', encoding="utf-8") as csvfile:
reader = csv.DictReader(csvfile)
ticks = {}
@@ -104,7 +114,7 @@ class Yahoo(BaseClient):
cookies = [cookiejar.Cookie(version=0,
name="B",
value="7pbfivtfkl00m&b=3&s=if",
port=None, port_specified=None,
port=None, port_specified=False,
domain=".yahoo.com", domain_specified=True, domain_initial_dot=True,
path="/", path_specified=True,
secure=True,
@@ -112,16 +122,20 @@ class Yahoo(BaseClient):
discard=False,
comment=None,
comment_url=None,
rest=None)
rest=dict())
]
try:
text = self.urlopen(url, redirect=True, data=None, headers=None, cookies=cookies)
with open(os.path.join(self.basedir, 'yahoo-{}.html'.format(ticker)), "w") as text_file:
except BaseException as e:
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Yahoo.getRealtime({}, {}) - urlopen: {}'.format(ticker, datacode, e)
try:
with open(os.path.join(self.basedir, 'yahoo-{}.html'.format(ticker)), "w", encoding="utf-8") as text_file:
print(f"<!-- '{url}' -->\r\n\r\n{text}", file=text_file)
except BaseException as e:
logger.error(traceback.format_exc())
return 'Yahoo.getRealtime({}, {}) - urlopen: {}'.format(ticker, datacode, e)
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
try:
text = urllib.parse.unquote(text)
@@ -135,7 +149,7 @@ class Yahoo(BaseClient):
self.crumb = match.group(1)
except BaseException as e:
logger.error(traceback.format_exc())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Yahoo.getRealtime({}, {}) - crumb: {}'.format(ticker, datacode, e)
try:
@@ -151,10 +165,10 @@ class Yahoo(BaseClient):
return None
except BaseException as e:
logger.error(traceback.format_exc())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Yahoo.getRealtime({}, {}) - parsing: {}'.format(ticker, datacode, e)
with open(os.path.join(self.basedir, 'yahoo-{}.js'.format(ticker)), "w") as text_file:
with open(os.path.join(self.basedir, 'yahoo-{}.js'.format(ticker)), "w", encoding="utf-8") as text_file:
print(f"// '{url}' QuoteSummaryStore:\n", file=text_file)
pprint.pprint(results.asList(), stream=text_file)
@@ -181,12 +195,23 @@ 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')), yearfirst=True, dayfirst=False).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'])
@@ -197,9 +222,16 @@ class Yahoo(BaseClient):
tick[Datacode.LAST_PRICE_DATE] = dt.date()
tick[Datacode.LAST_PRICE_TIME] = dt.time()
tick[Datacode.TICKER] = str(price['symbol'])
tick[Datacode.EXCHANGE] = str(price['exchange'])
tick[Datacode.CURRENCY] = str(price['currency'])
tick[Datacode.TICKER] = self.save_wrapper(lambda: str(price['symbol']))
tick[Datacode.EXCHANGE] = self.save_wrapper(lambda: str(price['exchange']))
tick[Datacode.CURRENCY] = self.save_wrapper(lambda: str(price['currency']))
# some Moscow symbols miss currency in data block but show it in text e.g. VTBBA.ME, TBIOA.ME
if not tick[Datacode.CURRENCY]:
r = r'Currency in ([A-Z]{3})\b'
match = re.compile(r, flags=re.DOTALL).search(text)
if match:
tick[Datacode.CURRENCY] = match.group(1)
name = price['longName'] or price['shortName']
if name:
@@ -208,15 +240,11 @@ class Yahoo(BaseClient):
tick[Datacode.NAME] = tick[Datacode.TICKER]
except BaseException as e:
logger.error(traceback.format_exc())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Yahoo.getRealtime({}, {}) - process: {}'.format(ticker, datacode, e)
try:
summaryProfile = results['summaryProfile']
tick[Datacode.SECTOR] = str(summaryProfile['sector'])
tick[Datacode.INDUSTRY] = str(summaryProfile['industry'])
except KeyError as e:
pass
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)
@@ -241,6 +269,12 @@ class Yahoo(BaseClient):
if Datacode.ADJ_CLOSE != datacode and ticker not in self.historicdata:
self._read_ticker_csv_file(ticker)
try:
date_as_dt = dateutil.parser.parse(date, yearfirst=True, dayfirst=False)
except BaseException as e:
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Yahoo.getHistoric({}, {}, {}) - date_as_dt: {}'.format(ticker, datacode, date, e)
if ticker in self.historicdata:
ticks = self.historicdata[ticker]
@@ -253,12 +287,12 @@ class Yahoo(BaseClient):
# (potentially) future date
if date > max(ticks):
t1 = int(dateutil.parser.parse(date).strftime('%s'))
t1 = int(date_as_dt.timestamp())
t2 = int(time.time())
if t1 > t2:
return 'Future date \'{}\''.format(date)
min_tick_date = int(dateutil.parser.parse(min(ticks)).strftime('%s')) # remember current earliest date
min_tick_date = int(dateutil.parser.parse(min(ticks), yearfirst=True, dayfirst=False).timestamp()) # remember current earliest date
if not self.crumb:
self.getRealtime(ticker, datacode)
@@ -267,7 +301,7 @@ class Yahoo(BaseClient):
return 'Yahoo.getHistoric({}, {}, {}) - crumb'.format(ticker, datacode, date)
try:
t1 = int(dateutil.parser.parse(date).strftime('%s'))
t1 = int(date_as_dt.timestamp())
t2 = int(time.time())
if min_tick_date:
@@ -276,13 +310,13 @@ class Yahoo(BaseClient):
if t1 >= t2:
return 'Future date \'{}\''.format(date)
if t1 < int(dateutil.parser.parse('2000-01-01').strftime('%s')):
if t1 < int(dateutil.parser.parse('2000-01-01', yearfirst=True, dayfirst=False).timestamp()):
return 'Date before 2000 \'{}\''.format(date)
t1 = t1 - 2682000 # pad with extra month
except BaseException as e:
logger.error(traceback.format_exc())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Yahoo.getHistoric({}, {}, {}) - date: {}'.format(ticker, datacode, date, e)
try:
@@ -293,18 +327,18 @@ class Yahoo(BaseClient):
text = self.urlopen(url)
with open(os.path.join(self.basedir, 'yahoo-{}.csv'.format(ticker)), "w") as csv_file:
with open(os.path.join(self.basedir, 'yahoo-{}.csv'.format(ticker)), "w", encoding="utf-8") as csv_file:
print(text, file=csv_file)
self._read_ticker_csv_file(ticker)
except HttpException:
logger.error(traceback.format_exc())
logger.exception("HttpException ticker=%s datacode=%s date=%s", ticker, datacode, date)
return None
except BaseException as e:
logger.error(traceback.format_exc())
return 'Yahoo.getHistoric({}, {}, {}) - read: {}'.format(ticker, datacode, date, e)
logger.exception("BaseException ticker=%s datacode=%s date=%s", ticker, datacode, date)
return 'Yahoo.getHistoric({}, {}, {}) - urlopen: {}'.format(ticker, datacode, date, e)
try:
if ticker in self.historicdata:
@@ -321,7 +355,7 @@ class Yahoo(BaseClient):
return 'Not a trading day \'{}\''.format(date)
except BaseException as e:
logger.error(traceback.format_exc())
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
return 'Yahoo.getHistoric({}, {}, {}) - process: {}'.format(ticker, datacode, date, e)
return None
+1 -1
View File
@@ -14,7 +14,7 @@ import os
cur_dir = os.getcwd()
addin_id = "com.financials.getinfo"
addin_version = "2.1.1"
addin_version = "2.5.1"
addin_displayname = "Financial Market Extension"
addin_publisher_link = "https://github.com/cmallwitz/Financials-Extension"
addin_publisher_name = "The Publisher"
+207 -145
View File
@@ -12,243 +12,305 @@ import logging
import sys
import unittest
logging.basicConfig(level=logging.ERROR, format="%(asctime)s %(name)s %(levelname)s %(message)s")
import financials
from datacode import Datacode
import testutils
financials = financials.createInstance(None)
logging.basicConfig(level=logging.ERROR)
class Test(unittest.TestCase):
def test_currency(self):
s = financials.getRealtime('EURGBP', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_currency LAST_PRICE')
s = financials.getRealtime('EURGBP', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_currency LAST_PRICE')
s = financials.getRealtime('EURGBP', Datacode.CURRENCY.value, 'FT')
self.assertEqual(type(s), str, 'test_currency CURRENCY')
s = financials.getRealtime('EURGBP', 'CURRENCY', 'FT')
self.assertEqual(str, type(s), 'test_currency CURRENCY')
def test_US_equity(self):
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.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity CHANGE {}'.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.CHANGE_IN_PERCENT.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity CHANGE_IN_PERCENT {}'.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.AVG_DAILY_VOL_3MOMTH.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity AVG_DAILY_VOL_3MOMTH {}'.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('INTC:NSQ', Datacode.MARKET_CAP.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity MARKET_CAP {}'.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.TICKER.value, 'FT')
self.assertEqual(type(s), str, 'test_US_equity TICKER {}'.format(s))
self.assertEqual(s, 'IBM:NYQ', 'test_US_equity TICKER {}'.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.PREV_CLOSE.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity PREV_CLOSE {}'.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.OPEN.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity OPEN {}'.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.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity LAST_PRICE {}'.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.LOW.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity LOW {}'.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.HIGH.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity HIGH {}'.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.VOLUME.value, 'FT')
self.assertEqual(type(s), float, 'test_US_equity VOLUME {}'.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.NAME.value, 'FT')
self.assertEqual(type(s), str, 'test_US_equity NAME {}'.format(s))
self.assertEqual(s, 'International Business Machines Corp',
'test_US_equity NAME {}'.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', Datacode.SECTOR.value, 'FT')
self.assertEqual(type(s), str, 'test_US_equity SECTOR {}'.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', Datacode.INDUSTRY.value, 'FT')
self.assertEqual(type(s), str, 'test_US_equity INDUSTRY {}'.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', Datacode.TIMEZONE.value, 'FT')
self.assertEqual(type(s), str, 'test_US_equity TIMEZONE {}'.format(s))
# may fail (s is None) on weekends when date/time displayed doesn't have time component with TZ
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', 'LAST_PRICE', 'FT')
self.assertEqual(float, type(s), 'test_US_mutuals LAST_PRICE {}'.format(s))
s = financials.getRealtime('VGSLX', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_US_mutuals LAST_PRICE {}'.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.NAME.value, 'FT')
self.assertEqual(s, "Vanguard Real Estate Index Fund Admiral Shares",
'test_US_mutuals NAME {}'.format(s))
s = financials.getRealtime('VGSLX', 'CURRENCY', 'FT')
self.assertEqual('USD', s, 'test_US_mutuals CURRENCY {}'.format(s))
s = financials.getRealtime('VGSLX', Datacode.CURRENCY.value, 'FT')
self.assertEqual(s, "USD", 'test_US_mutuals CURRENCY {}'.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.value, 'FT')
self.assertEqual(type(s), float, 'test_US_mutuals CHANGE {}'.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.CHANGE_IN_PERCENT.value, 'FT')
self.assertEqual(type(s), float, 'test_US_mutuals CHANGE_IN_PERCENT {}'.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_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_US_mutuals LAST_PRICE_DATE {}'.format(s))
s = financials.getRealtime('VFIAX', Datacode.LAST_PRICE_TIME.value, 'FT')
self.assertEqual(type(s), str, 'test_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('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('CSP1:LSE:GBX', Datacode.NAME.value, 'FT')
self.assertEqual(type(s), str, 'test_UK_ETF NAME {}'.format(s))
self.assertEqual(s, 'iShares Core S&P 500 UCITS ETF USD (Acc)',
'test_UK_ETF NAME {}'.format(s))
s = financials.getRealtime('C060:GER:EUR', 'NAME', 'FT')
self.assertEqual(str, type(s), 't_UK_ETF NAME {}'.format(s))
s = financials.getRealtime('C060:GER:EUR', Datacode.NAME.value, 'FT')
self.assertEqual(type(s), str, 't_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('VERX:LSE:GBP', Datacode.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_UK_ETF LAST_PRICE {}'.format(s))
s = financials.getRealtime('VERX:LSE:GBP', Datacode.TIMEZONE.value, 'FT')
self.assertEqual(type(s), str, 'test_UK_ETF TIMEZONE {}'.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', 'NAME', 'FT')
self.assertEqual('SAP SE', s, 'test_DE_equity NAME {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.NAME.value, 'FT')
self.assertEqual(s, "SAP SE", 'test_DE_equity NAME {}'.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.TICKER.value, 'FT')
self.assertEqual(s, "SAPX:GER", 'test_DE_equity TICKER {}'.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.CURRENCY.value, 'FT')
self.assertEqual(s, 'EUR', 'test_DE_equity CURRENCY {}'.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.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_DE_equity LAST_PRICE {}'.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_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_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_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_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_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_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_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_DE_equity MARKET_CAP {}'.format(s))
s = financials.getRealtime('SAPX:GER', Datacode.SECTOR.value, 'FT')
self.assertEqual(type(s), str, 'test_DE_equity SECTOR {}'.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', Datacode.INDUSTRY.value, 'FT')
self.assertEqual(type(s), str, 'test_DE_equity INDUSTRY {}'.format(s))
self.assertEqual(s, 'Software & Computer Services', 'test_DE_equity INDUSTRY {}'.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', Datacode.LAST_PRICE_DATE.value, 'FT')
self.assertEqual(type(s), str, 'test_DE_equity LAST_PRICE_DATE {}'.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', Datacode.TIMEZONE.value, 'FT')
self.assertEqual(type(s), str, 'test_DE_equity TIMEZONE {}'.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', Datacode.SECTOR.value, 'FT')
self.assertEqual(type(s), str, 'test_TY_equity SECTOR {}'.format(s))
self.assertEqual(s, 'Industrials', 'test_TY_equity SECTOR {}'.format(s))
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', Datacode.INDUSTRY.value, 'FT')
self.assertEqual(type(s), str, 'test_TY_equity INDUSTRY {}'.format(s))
self.assertEqual(s, 'General Industrials', 'test_TY_equity INDUSTRY {}'.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', 'ticker', 'FT')
self.assertEqual('INX:IOM', s, 'test_index TICKER {}'.format(s))
s = financials.getRealtime('INX:IOM', Datacode.TICKER.value, 'FT')
self.assertEqual(s, "INX:IOM", '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.TICKER.value, 'FT')
self.assertEqual(s, "DAXX:GER", 'test_index TICKER {}'.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.LAST_PRICE.value, 'FT')
self.assertEqual(type(s), float, 'test_index LAST_PRICE {}'.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.VOLUME.value, 'FT')
self.assertEqual(type(s), float, 'test_DE_equity VOLUME {}'.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.LOW_52_WEEK.value, 'FT')
self.assertEqual(type(s), float, 'test_DE_equity LOW_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.HIGH_52_WEEK.value, 'FT')
self.assertEqual(type(s), float, 'test_DE_equity HIGH_52_WEEK {}'.format(s))
s = financials.getRealtime('DAXX:GER', Datacode.OPEN.value, 'FT')
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')
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')
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')
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')
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')
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__':
parser = argparse.ArgumentParser()
+37 -37
View File
@@ -12,13 +12,13 @@ import logging
import sys
import unittest
logging.basicConfig(level=logging.ERROR, format="%(asctime)s %(name)s %(levelname)s %(message)s")
import financials
from datacode import Datacode
financials = financials.createInstance(None)
logging.basicConfig(level=logging.ERROR)
class Test(unittest.TestCase):
@@ -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')
@@ -112,32 +112,32 @@ class Test(unittest.TestCase):
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
+74 -44
View File
@@ -14,152 +14,181 @@ import pathlib
import sys
import unittest
logging.basicConfig(level=logging.ERROR, format="%(asctime)s %(name)s %(levelname)s %(message)s")
import financials
from datacode import Datacode
import testutils
financials = financials.createInstance(None)
logging.basicConfig(level=logging.ERROR)
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(type(s), str, 'test_realtime_US_equity SECTOR {}'.format(s))
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(type(s), str, 'test_realtime_US_equity INDUSTRY {}'.format(s))
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))
s = financials.getRealtime('IBM', Datacode.EXCHANGE.value, 'YAHOO')
self.assertEqual(s, 'NYQ', 'test_realtime_US_equity EXCHANGE')
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))
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(type(s), str, 'test_realtime_DE_equity SECTOR {}'.format(s))
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(type(s), str, 'test_realtime_DE_equity INDUSTRY {}'.format(s))
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('C060.DE', Datacode.NAME.value, 'YAHOO')
self.assertEqual(str, type(s), 'test_realtime_DE_equity NAME {}'.format(s))
s = financials.getRealtime('C060.DE', Datacode.EXCHANGE.value, 'YAHOO')
self.assertEqual(s, 'GER', 'test_realtime_DE_equity EXCHANGE')
def test_realtime_TY_equity(self):
s = financials.getRealtime('6503.T', Datacode.OPEN.value, 'YAHOO')
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('6503.T', Datacode.LOW.value, 'YAHOO')
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('6503.T', Datacode.HIGH.value, 'YAHOO')
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('6503.T', Datacode.LOW_52_WEEK.value, 'YAHOO')
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('6503.T', Datacode.HIGH_52_WEEK.value, 'YAHOO')
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('6503.T', Datacode.MARKET_CAP.value, 'YAHOO')
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('6503.T', Datacode.VOLUME.value, 'YAHOO')
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('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(type(s), str, 'test_TY_equity SECTOR {}'.format(s))
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(type(s), str, 'test_TY_equity INDUSTRY {}'.format(s))
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):
@@ -195,7 +224,7 @@ class Test(unittest.TestCase):
# 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(141.637695, s, 'test_historic_US_equity ADJ_CLOSE {}'.format(s))
self.assertEqual(139.61322, s, 'test_historic_US_equity ADJ_CLOSE {}'.format(s))
def test_historic_UK_ETF(self):
@@ -209,7 +238,7 @@ class Test(unittest.TestCase):
financials.yahoo.historicdata = {}
# Inception Date 2014-09-30
s = financials.getHistoric('VERX.L', Datacode.CLOSE.value, '2018-04-02', 'YAHOO') # Easter Monday
s = financials.getHistoric('VERX.L', Datacode.CLOSE.value, '2018-04-02', 'YAHOO') # Easter Monday
self.assertEqual(s, 'Not a trading day \'2018-04-02\'', 'test_historic_UK_ETF CLOSE {}'.format(s))
# Inception Date 2014-09-30
@@ -282,7 +311,8 @@ class Test(unittest.TestCase):
self.assertEqual(s, 'Date format not supported: \'abcdef\'', 'test_historic_errors CLOSE {}'.format(s))
s = financials.getHistoric('IBM', Datacode.CLOSE.value, True, 'YAHOO')
self.assertEqual(s, 'Date type not supported: <class \'bool\'> \'True\'', 'test_historic_errors CLOSE {}'.format(s))
self.assertEqual(s, 'Date type not supported: <class \'bool\'> \'True\'',
'test_historic_errors CLOSE {}'.format(s))
s = financials.getHistoric('IBM', Datacode.CLOSE.value, -1000000, 'YAHOO')
self.assertEqual(s, 'Date format not supported: -1000000', 'test_historic_errors CLOSE {}'.format(s))
+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