Last active
August 29, 2015 14:02
-
-
Save zdxerr/5796facee4c3c4c1e695 to your computer and use it in GitHub Desktop.
Stock analysis tool.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Accounts": { | |
"Comdirect Tagesgeld": { | |
"Actions": [ | |
{ | |
"Action": "payment", | |
"Date": "2014-06-10", | |
"Quantity": 1.0, | |
"Value": 2289.12 | |
} | |
], | |
"BIC": "COBADEHD044", | |
"IBAN": "DE22200411440496732900" | |
}, | |
"flatex Cashkonto": { | |
"Actions": [ | |
{ | |
"Action": "payment", | |
"Date": "2014-06-10", | |
"Quantity": 1.0, | |
"Value": 2604.11 | |
} | |
], | |
"BIC": "BIWBDE33XXX", | |
"IBAN": "DE24101308001000947715" | |
} | |
}, | |
"Stocks": { | |
"Sinopipe": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-02-03", | |
"Description": "", | |
"Quantity": 1000.0, | |
"Taxes": 0.0, | |
"Value": 0.2 | |
} | |
], | |
"Places": [ | |
"f" | |
], | |
"Symbol": "3si" | |
}, | |
"Bayer": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-09-26", | |
"Description": "TA.-Nr. 40345152", | |
"Quantity": 50.0, | |
"Taxes": 0.0, | |
"Value": 37.31 | |
}, | |
{ | |
"Action": "bonus", | |
"Cost": 0.0, | |
"Date": "2013-04-29", | |
"Description": "", | |
"Quantity": 50.0, | |
"Taxes": 25.05, | |
"Value": 1.9 | |
}, | |
{ | |
"Action": "sell", | |
"Cost": 7.02, | |
"Date": "2013-05-13", | |
"Description": "TA.-Nr. 590267786", | |
"Quantity": -50.0, | |
"Taxes": 605.45, | |
"Value": 83.5 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "bayn" | |
}, | |
"Commerzbank": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-02-03", | |
"Description": "", | |
"Quantity": 380.0, | |
"Taxes": 0.0, | |
"Value": 4.033 | |
}, | |
{ | |
"Action": "capital reduction", | |
"Cost": 0.0, | |
"Date": "2013-04-24", | |
"Description": "Kapitalherabsetzung", | |
"Quantity": -380.0, | |
"Taxes": 0.0, | |
"Value": 4.033 | |
}, | |
{ | |
"Action": "capital reduction", | |
"Cost": 0.0, | |
"Date": "2013-04-24", | |
"Description": "Kapitalherabsetzung", | |
"Quantity": 60.0, | |
"Taxes": 0.0, | |
"Value": 25.543000000000003 | |
}, | |
{ | |
"Action": "buy", | |
"Cost": 5.0, | |
"Date": "2013-05-31", | |
"Description": "Kapitalerh\u00f6hung", | |
"Quantity": 57.0, | |
"Taxes": 0.0, | |
"Value": 4.5 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "cbk" | |
}, | |
"cmid.f": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-02-03", | |
"Description": "", | |
"Quantity": 25.0, | |
"Taxes": 0.0, | |
"Value": 17.56 | |
}, | |
{ | |
"Action": "sell", | |
"Cost": 10.97, | |
"Date": "2013-09-20", | |
"Description": "", | |
"Quantity": -25.0, | |
"Taxes": 0.0, | |
"Value": 0.114 | |
} | |
], | |
"Places": [ | |
"f" | |
], | |
"Symbol": "cmid" | |
}, | |
"Deutsche Post": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-09-23", | |
"Description": "TA.-Nr. 403152122", | |
"Quantity": 80.0, | |
"Taxes": 0.0, | |
"Value": 9.0 | |
}, | |
{ | |
"Action": "sell", | |
"Cost": 6.99, | |
"Date": "2013-05-14", | |
"Description": "TA.-Nr. 590591860", | |
"Quantity": -80.0, | |
"Taxes": 213.67, | |
"Value": 19.3 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "dpw" | |
}, | |
"Forsys Metals": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-02-03", | |
"Description": "", | |
"Quantity": 2000.0, | |
"Taxes": 0.0, | |
"Value": 2.09425 | |
}, | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-03-16", | |
"Description": "TA.-Nr. 332738263", | |
"Quantity": 500.0, | |
"Taxes": 0.0, | |
"Value": 1.444 | |
}, | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-09-21", | |
"Description": "TA.-Nr. 402067343", | |
"Quantity": 1000.0, | |
"Taxes": 0.0, | |
"Value": 0.42 | |
}, | |
{ | |
"Action": "sell", | |
"Cost": 10.97, | |
"Date": "2013-11-26", | |
"Description": "", | |
"Quantity": -3500.0, | |
"Taxes": 0.0, | |
"Value": 0.265 | |
} | |
], | |
"Places": [ | |
"f" | |
], | |
"Symbol": "f2t" | |
}, | |
"njf.f": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-02-03", | |
"Description": "", | |
"Quantity": 1000.0, | |
"Taxes": 0.0, | |
"Value": 0.39799999999999996 | |
} | |
], | |
"Places": [ | |
"f" | |
], | |
"Symbol": "njf" | |
}, | |
"Thyssenkrupp": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2012-06-12", | |
"Description": "TA.-Nr. 489505577", | |
"Quantity": 100.0, | |
"Taxes": 0.0, | |
"Value": 12.0 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "tka" | |
}, | |
"Tesla Motors": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 7.01, | |
"Date": "2014-04-16", | |
"Description": "", | |
"Quantity": 15.0, | |
"Taxes": 0.0, | |
"Value": 142.0 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "tl0" | |
}, | |
"TUI": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 0.0, | |
"Date": "2011-09-14", | |
"Description": "TA.-Nr. 399498167", | |
"Quantity": 200.0, | |
"Taxes": 0.0, | |
"Value": 3.97 | |
}, | |
{ | |
"Action": "sell", | |
"Cost": 7.0, | |
"Date": "2013-05-13", | |
"Description": "TA.-Nr. 590260878", | |
"Quantity": -200.0, | |
"Taxes": 269.57, | |
"Value": 9.15 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "tui1" | |
}, | |
"Lufthansa": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 6.99, | |
"Date": "2014-06-17", | |
"Description": "TA-Nr. 62400143", | |
"Quantity": 100.0, | |
"Taxes": 0.0, | |
"Value": 16.0 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "lha" | |
}, | |
"Daimler": { | |
"Actions": [ | |
{ | |
"Action": "buy", | |
"Cost": 7.1, | |
"Date": "2014-07-28", | |
"Description": "TA-Nr. 742154935", | |
"Quantity": 30.0, | |
"Taxes": 0.0, | |
"Value": 65.0 | |
} | |
], | |
"Places": [ | |
"de" | |
], | |
"Symbol": "dai" | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
""" | |
import csv | |
import decimal | |
import functools | |
import requests | |
import pandas | |
from pandas.io.data import DataReader | |
from datetime import datetime, date | |
import dateutil | |
import collections | |
from pprint import pprint | |
import logging | |
logger = logging.getLogger(__name__) | |
from utils import JSONFile | |
YAHOO_TODAY_URL = 'http://download.finance.yahoo.com/d/quotes.csv' | |
YAHOO_TODAY_FORMAT = 'sd1ohgl1vl1' | |
class Stock: | |
def __init__(self, symbol, locations): | |
self.symbol = symbol | |
self.locations = locations | |
def __str__(self): | |
return '%s.%s' % (self.symbol, self.locations[0]) | |
@functools.lru_cache() | |
def today(self): | |
params = { | |
's': str(self), | |
'f': YAHOO_TODAY_FORMAT, | |
} | |
response = requests.get(YAHOO_TODAY_URL, params=params) | |
reader = csv.reader( | |
response.text.splitlines(), | |
delimiter=',', | |
quotechar='"', | |
) | |
name, date_str, *values = next(reader) | |
today = dateutil.parser.parse(date_str) | |
df = pandas.DataFrame( | |
index=pandas.DatetimeIndex(start=today, end=today, freq='D'), | |
columns=['Open', 'High', 'Low', 'Close', 'Volume', 'Adj Close'], | |
dtype=decimal.Decimal) | |
df.ix[0] = list(map(decimal.Decimal, values)) | |
return df | |
@functools.lru_cache() | |
def history(self, since=datetime(2010,1,1)): | |
history = DataReader( | |
str(self), | |
'yahoo', | |
datetime(2012,1,1), | |
datetime.today(), | |
) | |
return history.append(self.today()) | |
def _asdict(self): | |
return { | |
'symbol': self.symbol, | |
'locations': self.locations, | |
} | |
if __name__ == '__main__': | |
logging.basicConfig(level=logging.DEBUG) | |
stock = Stock('cbk', ['de']) | |
# print(stock.history()) | |
pprint(stock._asdict()) | |
data = JSONFile('moneymaker.json') | |
stocks = data.setdefault('Stocks', dict()) | |
for name, infos in stocks.items(): | |
# print(name) | |
s = Stock(infos['Symbol'], infos['Places']) | |
print(s) | |
actions = infos.get('Actions', list()) | |
s.actions = pandas.DataFrame(actions, columns=['Date', 'Action', 'Quantity', 'Value', 'Description']) | |
from dateutil import parser | |
s.actions['Date'] = s.actions['Date'].map(parser.parse) | |
print(s.actions) | |
# pprint(stocks) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Utility classes and functions. | |
""" | |
import os | |
import json | |
import collections | |
import decimal | |
import logging | |
logger = logging.getLogger(__name__) | |
class JSONFile(dict): | |
""" | |
Handle JSON files. | |
""" | |
def __init__(self, path): | |
super(JSONFile, self).__init__() | |
self.path = os.path.abspath(path) | |
logger.debug("Open JSON file `%s`", path) | |
try: | |
with open(path) as fp: | |
try: | |
self.update(json.load( | |
fp, | |
object_pairs_hook=collections.OrderedDict, | |
parse_float=decimal.Decimal, | |
)) | |
except ValueError: | |
logger.error("Invalid json file: %s", path) | |
except FileNotFoundError: | |
logger.warn("File not found `%s`", path) | |
self.flush() | |
@classmethod | |
def decimal_default(cls, obj): | |
""" | |
Decimal handler for JSON endocding. | |
""" | |
try: | |
return obj._asdict() | |
except AttributeError: | |
pass | |
try: | |
return float(obj) | |
except IOError: | |
pass | |
raise TypeError("Not serializeable %r of type %s." % (obj, type(obj))) | |
def to_json(self): | |
""" | |
Dumpt formated string of the files contents. | |
""" | |
return json.dumps(self, | |
indent=4, | |
sort_keys=True, | |
default=self.decimal_default | |
) | |
def flush(self): | |
"""Save changes to file.""" | |
try: | |
os.makedirs(os.path.dirname(self.path)) | |
except FileExistsError: | |
pass | |
with open(self.path, 'w+') as fp: | |
logger.debug("Write to `%s`", self.path) | |
fp.write(self.to_json()) | |
if __name__ == '__main__': | |
from pprint import pprint | |
logging.basicConfig(level=logging.DEBUG) | |
json_file = JSONFile('test.json') | |
json_file['dec'] = decimal.Decimal('1.0000000001') | |
print(json_file) | |
json_file.flush() | |
json_read = JSONFile('test.json') | |
print(str(json_read)) | |
pprint(dict(json_read)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment