mirror of
https://github.com/cmallwitz/Financials-Extension.git
synced 2026-08-25 10:04:10 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
605e9ef185 | ||
|
|
e0491318c3 | ||
|
|
24b1406772 | ||
|
|
1d9c4e824f | ||
|
|
c3a6d8d69a | ||
|
|
d0fc0ae2bf | ||
|
|
e4d395240d | ||
|
|
c3dc5c35fc | ||
|
|
b356a1bca4 | ||
|
|
befd0956f0 | ||
|
|
9e842b30de | ||
|
|
6d0f56c87d | ||
|
|
cd41959559 | ||
|
|
52e7119081 | ||
|
|
520d2441cb |
@@ -2,13 +2,8 @@
|
||||
|
||||
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 and Financial Times' finance websites using old-fashioned web scraping.
|
||||
Starting with version 3 of the extension, Google was dropped as source as its finance website was changed dramatically
|
||||
requiring a complete re-work of the logic to pull data of it. No one seems to have complained, so I guess not a lot of
|
||||
people rely on it. If there is popular demand, I can take a look at adding it back. Alternatively I'm open for
|
||||
suggestions to add another provider with global exchange and asset class coverage.
|
||||
|
||||
Additionally, starting with version 3 of the extension, it contains all non-standard Python packages it uses
|
||||
(dateutil, pytz, pyparsing). Consequently, it is no longer necessary to install anything to your system.
|
||||
Starting with version 3.1.0, we received a contribution to get crypto data directly from Coinbase
|
||||
|
||||
### Feedback requested:
|
||||
|
||||
@@ -21,11 +16,12 @@ under menu item: Tools, Extension Manager...
|
||||
|
||||
Please make sure, not to rename the OXT file when downloading and before installing: LO will mess up the installation otherwise and the extension won't work.
|
||||
|
||||
Getting data should be a simple as having this in a cell:
|
||||
Getting data should be as simple as having this in a cell:
|
||||
- `=GETREALTIME("IBM",21,"YAHOO")`
|
||||
- `=GETREALTIME("IBM:NYQ",21,"FT")`
|
||||
- `=GETREALTIME("EURUSD","LAST_PRICE","FT")`
|
||||
- `=GETHISTORIC("IBM",90,"2020-12-01","YAHOO")`
|
||||
- `=GETREALTIME("ETH-USD","LAST_PRICE","COINBASE")`
|
||||
|
||||
Codes 21 and 90 stand for "last price" and "close" (see below), respectively.
|
||||
Only Yahoo has historic data available.
|
||||
@@ -43,10 +39,11 @@ List of example URLs for checking symbols. You can start from these and search f
|
||||
is available on the website but not from the extension, a good place to start when raising an issue is to include a similar
|
||||
URL to compare results.
|
||||
|
||||
|Website|Symbol|Example URL for Vodafone Group Plc UK |
|
||||
| :--- | :--- | :--- |
|
||||
|YAHOO|VOD.L|https://finance.yahoo.com/quote/VOD.L|
|
||||
|FT|VOD:LSE|https://markets.ft.com/data/equities/tearsheet/summary?s=VOD:LSE|
|
||||
| Website | Symbol | Example URL for Vodafone Group Plc UK |
|
||||
|:---------|:--------|:-----------------------------------------------------------------|
|
||||
| YAHOO | VOD.L | https://finance.yahoo.com/quote/VOD.L |
|
||||
| FT | VOD:LSE | https://markets.ft.com/data/equities/tearsheet/summary?s=VOD:LSE |
|
||||
| COINBASE | ETH-EUR | https://api.exchange.coinbase.com/products/ETH-EUR/stats |
|
||||
|
||||
### LibreOffice: using , (comma) vs ; (semicolon) to separate arguments in formula
|
||||
|
||||
@@ -58,47 +55,47 @@ Depending on your system's language and default LibreOffice settings, you maybe
|
||||
|
||||
### 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.
|
||||
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|YAHOO (historic)|Notes|
|
||||
| :--- | :--- | :---: | :---: | :---: | :---: |
|
||||
|PREV_CLOSE|5|Yes|Yes|||
|
||||
|OPEN|6|Yes|Yes|Yes||
|
||||
|CHANGE|7|Yes|Yes|||
|
||||
|LAST_PRICE_DATE|8|Yes|Yes| |yyyy-mm-dd|
|
||||
|LAST_PRICE_TIME|10|Yes|Yes|||
|
||||
|CHANGE_IN_PERCENT|11|Yes|Yes|||
|
||||
|LOW|14|Yes|Yes|Yes||
|
||||
|HIGH|16|Yes|Yes|Yes||
|
||||
|LAST_PRICE|21|Yes|Yes|||
|
||||
|BID|22|Yes|Yes|||
|
||||
|ASK|25|Yes|Yes|||
|
||||
|HIGH_52_WEEK|24|Yes|Yes|||
|
||||
|LOW_52_WEEK|26|Yes|Yes|||
|
||||
|MARKET_CAP|27|Yes|Yes|||
|
||||
|BIDSIZE|30|Yes|Yes|||
|
||||
|ASKSIZE|31|Yes|Yes|||
|
||||
|VOLUME|35|Yes|Yes|Yes||
|
||||
|AVG_DAILY_VOL_3MONTH|39|Yes|Yes|||
|
||||
|BETA|67|Yes|Yes|||
|
||||
|EPS|68|Yes|Yes|||
|
||||
|PE_RATIO|69|Yes|Yes|||
|
||||
|DIV|70|Yes|Yes|||
|
||||
|DIV_YIELD|71|Yes|Yes|||
|
||||
|EX_DIV_DATE|72|Yes|Yes| |yyyy-mm-dd|
|
||||
|PAYOUT_RATIO|73|Yes|No|||
|
||||
|EXPIRY_DATE|74|Yes (on options)|No| |yyyy-mm-dd|
|
||||
|SHARES_OUT|75|Yes|Yes| ||
|
||||
|FREE_FLOAT|76|Yes|Yes| ||
|
||||
|CLOSE|90|No|No|Yes||
|
||||
|ADJ_CLOSE|91|No|No|Yes||
|
||||
|SECTOR|98|Yes|Yes|||
|
||||
|INDUSTRY|99|Yes|Yes|||
|
||||
|TICKER|101|Yes|Yes|||
|
||||
|EXCHANGE|102|Yes|No|||
|
||||
|CURRENCY|103|Yes|Yes|||
|
||||
|NAME|104|Yes|Yes|||
|
||||
|TIMEZONE|105|Yes|Yes|||
|
||||
| Name | Code | YAHOO | FT | YAHOO (historic) | COINBASE | Notes |
|
||||
|:---------------------|:-----|:----------------:|:---:|:----------------:|----------|:----------:|
|
||||
| PREV_CLOSE | 5 | Yes | Yes |||
|
||||
| OPEN | 6 | Yes | Yes | Yes | Yes ||
|
||||
| CHANGE | 7 | Yes | Yes |||
|
||||
| LAST_PRICE_DATE | 8 | Yes | Yes | | | yyyy-mm-dd |
|
||||
| LAST_PRICE_TIME | 10 | Yes | Yes |||
|
||||
| CHANGE_IN_PERCENT | 11 | Yes | Yes |||
|
||||
| LOW | 14 | Yes | Yes | Yes | Yes ||
|
||||
| HIGH | 16 | Yes | Yes | Yes | Yes ||
|
||||
| LAST_PRICE | 21 | Yes | Yes | | Yes |
|
||||
| BID | 22 | Yes | Yes |||
|
||||
| ASK | 25 | Yes | Yes |||
|
||||
| HIGH_52_WEEK | 24 | Yes | Yes |||
|
||||
| LOW_52_WEEK | 26 | Yes | Yes |||
|
||||
| MARKET_CAP | 27 | Yes | Yes |||
|
||||
| BIDSIZE | 30 | Yes | Yes |||
|
||||
| ASKSIZE | 31 | Yes | Yes |||
|
||||
| VOLUME | 35 | Yes | Yes | Yes | Yes ||
|
||||
| AVG_DAILY_VOL_3MONTH | 39 | Yes | Yes |||
|
||||
| BETA | 67 | Yes | Yes |||
|
||||
| EPS | 68 | Yes | Yes |||
|
||||
| PE_RATIO | 69 | Yes | Yes |||
|
||||
| DIV | 70 | Yes | Yes |||
|
||||
| DIV_YIELD | 71 | Yes | Yes |||
|
||||
| EX_DIV_DATE | 72 | Yes | Yes | | | yyyy-mm-dd |
|
||||
| PAYOUT_RATIO | 73 | Yes | No |||
|
||||
| EXPIRY_DATE | 74 | Yes (on options) | No | | | yyyy-mm-dd |
|
||||
| SHARES_OUT | 75 | Yes | Yes | | ||
|
||||
| FREE_FLOAT | 76 | Yes | Yes | | ||
|
||||
| CLOSE | 90 | No | No | Yes | ||
|
||||
| ADJ_CLOSE | 91 | No | No | Yes | ||
|
||||
| SECTOR | 98 | Yes | Yes |||
|
||||
| INDUSTRY | 99 | Yes | Yes |||
|
||||
| TICKER | 101 | Yes | Yes | | Yes |
|
||||
| EXCHANGE | 102 | Yes | No |||
|
||||
| CURRENCY | 103 | Yes | Yes | | Yes |
|
||||
| NAME | 104 | Yes | Yes |||
|
||||
| TIMEZONE | 105 | Yes | Yes |||
|
||||
|
||||
### Dealing with missing data:
|
||||
|
||||
@@ -133,8 +130,8 @@ python3 -m unittest discover src
|
||||
|
||||
### Tested with:
|
||||
- Windows 10 / LibreOffice Calc 7.1.2.2 / Python 3.8.8
|
||||
- Ubuntu 20.04 / LibreOffice Calc 6.4.3.2 / Python 3.8.2
|
||||
- MacOS 10.15.7 / LibeOffice Calc 7.2.0.4 / Python 3.8.10
|
||||
- Ubuntu 20.04.5 / LibreOffice Calc 6.4.7.2 / Python 3.8.10
|
||||
- MacOS 10.15.7 / LibreOffice Calc 7.2.0.4 / Python 3.8.10
|
||||
|
||||
(Previous versions)
|
||||
- Debian 10.3 / LibreOffice Calc 6.1.5.2 / Python 3.7.3
|
||||
|
||||
+15
-2
@@ -5,8 +5,20 @@ set -o nounset
|
||||
set -o pipefail
|
||||
set -o noclobber
|
||||
|
||||
export PATH=$PATH:/usr/lib/libreoffice/sdk/bin
|
||||
export PATH=$PATH:/usr/lib/libreoffice/program
|
||||
if [[ $OSTYPE == "darwin"* ]]; then
|
||||
echo MacOS
|
||||
# Assuming both are installed in the applications folder
|
||||
# Required some steps to make it work for MacOS M1, mind the `find` call which could return more than one (shouldn't)
|
||||
# install_name_tool -change @__VIA_LIBRARY_PATH__/libreglo.dylib $(find /Applications -name "libreglo.dylib") /Applications/LibreOffice7.4_SDK/bin/idlc
|
||||
# install_name_tool -change @__VIA_LIBRARY_PATH__/libuno_sal.dylib.3 $(find /Applications -name "libuno_sal.dylib.3") /Applications/LibreOffice7.4_SDK/bin/idlc
|
||||
# install_name_tool -change @__VIA_LIBRARY_PATH__/libuno_salhelpergcc3.dylib.3 $(find /Applications -name "libuno_salhelpergcc3.dylib.3") /Applications/LibreOffice7.4_SDK/bin/idlc
|
||||
# codesign --force -s - $(find /Applications -name "idlc")
|
||||
export PATH=$PATH:/Applications/LibreOffice7.4_SDK/bin
|
||||
export PATH=$PATH:/Applications/LibreOffice.app/Contents/MacOS
|
||||
else
|
||||
export PATH=$PATH:/usr/lib/libreoffice/sdk/bin
|
||||
export PATH=$PATH:/usr/lib/libreoffice/program
|
||||
fi
|
||||
|
||||
# Setup build directories
|
||||
|
||||
@@ -37,6 +49,7 @@ cp -f "${PWD}"/src/tz.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/
|
||||
cp -f "${PWD}"/src/financials_coinbase.py "${PWD}"/build/
|
||||
|
||||
# this copies python modules dateutil, pytz, pyparsing to extension so it doesn't have to be installed by user
|
||||
|
||||
|
||||
Binary file not shown.
+9
-15
@@ -48,23 +48,17 @@ class BaseClient:
|
||||
os.makedirs(self.basedir, exist_ok=True)
|
||||
|
||||
user_agents = [
|
||||
'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 (X11; Ubuntu; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:92.0) Gecko/20100101 Firefox/92.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/96.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/97.0',
|
||||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/97.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',
|
||||
|
||||
@@ -56,6 +56,7 @@ import six
|
||||
from datacode import Datacode
|
||||
import financials_google as google
|
||||
import financials_yahoo as yahoo
|
||||
import financials_coinbase as coinbase
|
||||
import financials_ft as ft
|
||||
|
||||
implementation_name = "com.financials.getinfo.python.FinancialsImpl" # as defined in Financials.xcu
|
||||
@@ -96,6 +97,7 @@ class FinancialsImpl(unohelper.Base, Financials):
|
||||
self.ctx = ctx
|
||||
self.google = google.createInstance(ctx)
|
||||
self.yahoo = yahoo.createInstance(ctx)
|
||||
self.coinbase = coinbase.createInstance(ctx)
|
||||
self.ft = ft.createInstance(ctx)
|
||||
|
||||
@profile
|
||||
@@ -141,6 +143,8 @@ class FinancialsImpl(unohelper.Base, Financials):
|
||||
s = self.yahoo.getRealtime(ticker, datacode)
|
||||
elif source == 'FT':
|
||||
s = self.ft.getRealtime(ticker, datacode)
|
||||
elif source == 'COINBASE':
|
||||
s = self.coinbase.getRealtime(ticker, datacode)
|
||||
else:
|
||||
s = 'Source \'{}\' not supported'.format(source)
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# financials_coinbase.py
|
||||
#
|
||||
# license: GNU LGPL
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 3 of the License, or (at your option) any later version.
|
||||
|
||||
|
||||
import csv
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import pprint
|
||||
import re
|
||||
import time
|
||||
import json
|
||||
|
||||
import dateutil.parser
|
||||
import pytz
|
||||
|
||||
import jsonParser
|
||||
from baseclient import BaseClient, HttpException
|
||||
from datacode import Datacode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# logger.setLevel(logging.DEBUG)
|
||||
|
||||
class Coinbase(BaseClient):
|
||||
def __init__(self, ctx):
|
||||
super().__init__()
|
||||
|
||||
self.crumb = None
|
||||
self.realtime = {}
|
||||
self.js = jsonParser.jsonObject
|
||||
|
||||
def getRealtime(self, ticker, datacode):
|
||||
|
||||
"""
|
||||
Retrieve realtime data for ticker from Coinbase and cache it for further lookups
|
||||
|
||||
:param ticker: the ticker symbol e.g. ETH-EUR
|
||||
:param datacode: the requested datacode, not all are supported
|
||||
:return:
|
||||
"""
|
||||
|
||||
# remove white space
|
||||
ticker = "".join(ticker.split())
|
||||
|
||||
# use cached value for up to 60 seconds
|
||||
if ticker in self.realtime:
|
||||
tick = self.realtime[ticker]
|
||||
if time.time() - 60 < tick[Datacode.TIMESTAMP]:
|
||||
return self._return_value(tick, datacode)
|
||||
else:
|
||||
del self.realtime[ticker]
|
||||
|
||||
url = 'https://api.exchange.coinbase.com/products/{}/stats'.format(ticker)
|
||||
|
||||
try:
|
||||
text = self.urlopen(url, redirect=True, data=None, headers=None)
|
||||
except BaseException as e:
|
||||
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
|
||||
return 'Coinbase.getRealtime({}, {}) - urlopen: {}'.format(ticker, datacode, e)
|
||||
|
||||
try:
|
||||
with open(os.path.join(self.basedir, 'coinbase-{}.json'.format(ticker)), "w", encoding="utf-8") as text_file:
|
||||
print(f"<!-- '{url}' -->\r\n\r\n{text}", file=text_file)
|
||||
except BaseException:
|
||||
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
|
||||
|
||||
try:
|
||||
results = json.loads(text)
|
||||
|
||||
except BaseException as e:
|
||||
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
|
||||
return 'Coinbase.getRealtime({}, {}) - crumb: {}'.format(ticker, datacode, e)
|
||||
|
||||
try:
|
||||
price = results['last']
|
||||
|
||||
if not price:
|
||||
return 'Could not find price for \'{}\''.format(ticker)
|
||||
|
||||
if ticker not in self.realtime:
|
||||
self.realtime[ticker] = self.get_ticker()
|
||||
|
||||
tick = self.realtime[ticker]
|
||||
|
||||
tick[Datacode.TIMESTAMP] = time.time()
|
||||
tick[Datacode.LAST_PRICE] = float(price)
|
||||
tick[Datacode.OPEN] = float(results['open'])
|
||||
tick[Datacode.HIGH] = float(results['high'])
|
||||
tick[Datacode.LOW] = float(results['low'])
|
||||
tick[Datacode.VOLUME] = float(results['volume'])
|
||||
tick[Datacode.TICKER] = ticker.split('-', 1)[0]
|
||||
tick[Datacode.CURRENCY] = ticker.split('-', 1)[1]
|
||||
|
||||
except BaseException as e:
|
||||
logger.exception("BaseException ticker=%s datacode=%s", ticker, datacode)
|
||||
return 'Coinbase.getRealtime({}, {}) - process: {}'.format(ticker, datacode, e)
|
||||
|
||||
return self._return_value(self.realtime[ticker], datacode)
|
||||
|
||||
def createInstance(ctx):
|
||||
return Coinbase(ctx)
|
||||
+11
-9
@@ -118,14 +118,16 @@ class Yahoo(BaseClient):
|
||||
|
||||
url = 'https://finance.yahoo.com/quote/{}?p={}'.format(ticker, ticker)
|
||||
|
||||
cookies = [cookie("B", "7ndehflgtham3&b=3&s=mj"),
|
||||
# cookie("EuConsent", "CPSdqzyPSdqzyAOACCENBtCgAAAAAAAAACiQAAAAAABhoAMAAQQSEQAYAAggkKgAwABBBIA"),
|
||||
# cookie("GUCS", "AXdLQ12J"),
|
||||
# cookie("GUC", "AQABBgFh2flitkIiiATt"),
|
||||
cookie("A1", "d=AQABBOWq2GECEEvniMgJGWLsxf5dOz0WanAFEgABBgH52WG2YuA9b2UBgiAAAAcIw6rYYX3RtXs&S=AQAAAlFbjg2RcxWpwb48DGGofUE"),
|
||||
cookie("A1S", "d=AQABBOWq2GECEEvniMgJGWLsxf5dOz0WanAFEgABBgH52WG2YuA9b2UBgiAAAAcIw6rYYX3RtXs&S=AQAAAlFbjg2RcxWpwb48DGGofUE&j=GDPR"),
|
||||
cookie("A3", "d=AQABBOWq2GECEEvniMgJGWLsxf5dOz0WanAFEgABBgH52WG2YuA9b2UBgiAAAAcIw6rYYX3RtXs&S=AQAAAlFbjg2RcxWpwb48DGGofUE")
|
||||
]
|
||||
cookies = [
|
||||
cookie("A1", "d=AQABBDcIZWMCEHYhFYqQ7qyTvvD2eAT87mcFEgABCAGDlGPBY_bPb2UB9qMAAAcILwhlY6iIogg&S=AQAAAjZvTuAn1nH4h71eKJtCEHk"),
|
||||
cookie("A1S", "d=AQABBDcIZWMCEHYhFYqQ7qyTvvD2eAT87mcFEgABCAGDlGPBY_bPb2UB9qMAAAcILwhlY6iIogg&S=AQAAAjZvTuAn1nH4h71eKJtCEHk&j=GDPR"),
|
||||
cookie("A3", "d=AQABBDcIZWMCEHYhFYqQ7qyTvvD2eAT87mcFEgABCAGDlGPBY_bPb2UB9qMAAAcILwhlY6iIogg&S=AQAAAjZvTuAn1nH4h71eKJtCEHk"),
|
||||
cookie("GUC", "AQABCAFjlINjwUIcFQQQ&s=AQAAAFOQKXn7&g=Y5M5Jg"),
|
||||
cookie("GUCS", "ASHFadZS"),
|
||||
cookie("maex", "{\"v2\":{}}"),
|
||||
cookie("PRF", "t=TQQQ%2BASTO.L%2BCHMI%2BVFIAX%2BIBM%2BXMR-USD%2BMVV%2BSECU-B.ST%2BMSFT"),
|
||||
cookie("thamba", "1")
|
||||
]
|
||||
|
||||
try:
|
||||
text = self.urlopen(url, redirect=True, data=None, headers=None, cookies=cookies)
|
||||
@@ -312,7 +314,7 @@ class Yahoo(BaseClient):
|
||||
self.getRealtime(ticker, datacode)
|
||||
|
||||
if not self.crumb:
|
||||
return 'Yahoo.getHistoric({}, {}, {}) - crumb'.format(ticker, datacode, date)
|
||||
return 'Yahoo.getHistoric({}, {}, {}) - crumb missing'.format(ticker, datacode, date)
|
||||
|
||||
try:
|
||||
t1 = int(date_as_dt.timestamp())
|
||||
|
||||
@@ -14,7 +14,7 @@ import os
|
||||
cur_dir = os.getcwd()
|
||||
|
||||
addin_id = "com.financials.getinfo"
|
||||
addin_version = "3.0.6"
|
||||
addin_version = "3.1.0"
|
||||
addin_displayname = "Financial Market Extension"
|
||||
addin_publisher_link = "https://github.com/cmallwitz/Financials-Extension"
|
||||
addin_publisher_name = "The Publisher"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# test_yahoo.py
|
||||
#
|
||||
# license: GNU LGPL
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 3 of the License, or (at your option) any later version.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
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)
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def test_currency(self):
|
||||
s = financials.getRealtime('ETH-EUR', Datacode.LAST_PRICE.value, 'COINBASE')
|
||||
self.assertEqual(float, type(s), 'test_currency LAST_PRICE')
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('unittest_args', nargs='*')
|
||||
args = parser.parse_args()
|
||||
unit_argv = [sys.argv[0]] + args.unittest_args
|
||||
unittest.main(argv=unit_argv)
|
||||
+26
-26
@@ -102,7 +102,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
s = financials.getRealtime('IBM:NYQ', 'INDUSTRY', 'FT')
|
||||
self.assertEqual(str, type(s), 'test_US_equity INDUSTRY {}'.format(s))
|
||||
self.assertEqual(s, 'Software and Computer Services', 'test_US_equity INDUSTRY {}'.format(s))
|
||||
self.assertEqual(s, 'Technology', 'test_US_equity INDUSTRY {}'.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')
|
||||
@@ -208,7 +208,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
s = financials.getRealtime('SAPX:GER', 'INDUSTRY', 'FT')
|
||||
self.assertEqual(str, type(s), 'test_DE_equity INDUSTRY {}'.format(s))
|
||||
self.assertEqual('Software and Computer Services', s, 'test_DE_equity INDUSTRY {}'.format(s))
|
||||
self.assertEqual('Technology', 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))
|
||||
@@ -311,40 +311,40 @@ class Test(unittest.TestCase):
|
||||
self.assertEqual('General Industrials', s, 'test_TY_equity INDUSTRY {}'.format(s))
|
||||
|
||||
def test_TLV_equity(self):
|
||||
s = financials.getRealtime('DELT:TLV', 'LAST_PRICE', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity LAST_PRICE {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'LAST_PRICE', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity LAST_PRICE {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'OPEN', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity OPEN {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'OPEN', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity OPEN {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'LOW', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity LOW {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'LOW', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity LOW {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'HIGH', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity HIGH {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'HIGH', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity HIGH {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'LOW_52_WEEK', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity LOW_52_WEEK {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'LOW_52_WEEK', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity LOW_52_WEEK {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'HIGH_52_WEEK', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity HIGH_52_WEEK {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'HIGH_52_WEEK', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity HIGH_52_WEEK {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'MARKET_CAP', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity MARKET_CAP {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'MARKET_CAP', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity MARKET_CAP {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'VOLUME', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TlV_equity VOLUME {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'VOLUME', 'FT')
|
||||
self.assertEqual(float, type(s), 'test_TLV_equity VOLUME {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'CURRENCY', 'FT')
|
||||
self.assertEqual('ILa', s, 'test_TlV_equity CURRENCY')
|
||||
s = financials.getRealtime('LUMI:TLV', 'CURRENCY', 'FT')
|
||||
self.assertEqual('ILa', s, 'test_TLV_equity CURRENCY')
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'SECTOR', 'FT')
|
||||
self.assertEqual(str, type(s), 'test_TlV_equity SECTOR {}'.format(s))
|
||||
self.assertEqual('Consumer Discretionary', s, 'test_TY_equity SECTOR {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'SECTOR', 'FT')
|
||||
self.assertEqual(str, type(s), 'test_TLV_equity SECTOR {}'.format(s))
|
||||
self.assertEqual('Financials', s, 'test_TY_equity SECTOR {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('DELT:TLV', 'INDUSTRY', 'FT')
|
||||
self.assertEqual(str, type(s), 'test_TlV_equity INDUSTRY {}'.format(s))
|
||||
self.assertEqual('Personal Goods', s, 'test_TY_equity INDUSTRY {}'.format(s))
|
||||
s = financials.getRealtime('LUMI:TLV', 'INDUSTRY', 'FT')
|
||||
self.assertEqual(str, type(s), 'test_TLV_equity INDUSTRY {}'.format(s))
|
||||
self.assertEqual('Banks', s, 'test_TY_equity INDUSTRY {}'.format(s))
|
||||
|
||||
def test_index(self):
|
||||
s = financials.getRealtime('INX:IOM', 'ticker', 'FT')
|
||||
|
||||
+5
-6
@@ -175,12 +175,11 @@ class Test(unittest.TestCase):
|
||||
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))
|
||||
self.assertEqual('Europe/London', s, 'test_realtime_UK_ETF TIMEZONE {}'.format(s))
|
||||
|
||||
s = financials.getRealtime('CSP1.L', Datacode.NAME.value, 'YAHOO')
|
||||
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))
|
||||
self.assertEqual('iShares Core S&P 500 UCITS ETF USD (Acc)', s, 'test_realtime_UK_ETF NAME {}'.format(s))
|
||||
|
||||
def test_realtime_DE_equity(self):
|
||||
|
||||
@@ -188,11 +187,11 @@ class Test(unittest.TestCase):
|
||||
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))
|
||||
self.assertEqual('Europe/Berlin', s, '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))
|
||||
self.assertEqual('Technology', s, '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))
|
||||
@@ -331,7 +330,7 @@ class Test(unittest.TestCase):
|
||||
self.assertEqual(s, 82.889999, 'test_historic_DE_equity CLOSE {}'.format(s))
|
||||
|
||||
s = financials.getHistoric('C060.DE', Datacode.CLOSE.value, '2017-01-03', 'YAHOO')
|
||||
self.assertEqual(s, 68.209999, 'test_historic_DE_equity CLOSE {}'.format(s))
|
||||
self.assertEqual(s, 72.870003, 'test_historic_DE_equity CLOSE {}'.format(s))
|
||||
|
||||
def test_realtime_errors(self):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user