Skip to content

Commit

Permalink
Exported class
Browse files Browse the repository at this point in the history
  • Loading branch information
ilcardella committed Jan 27, 2019
1 parent 0022a69 commit b26e5c4
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 77 deletions.
110 changes: 33 additions & 77 deletions src/Model/Model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,79 +8,26 @@
import urllib.request
import json

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
currentdir = os.path.dirname(os.path.abspath(
inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)
sys.path.insert(0, parentdir)

from Utils.TaskThread import TaskThread
from Utils.Utils import Messages, Actions, Callbacks
from .StockPriceGetter import StockPriceGetter
from .Portfolio import Portfolio
from Utils.Utils import Messages, Actions, Callbacks
from Utils.TaskThread import TaskThread

class LivePricesWebThread(TaskThread):

def __init__(self, configurationManager, onNewPriceDataCallback, updatePeriod):
TaskThread.__init__(self, updatePeriod)
self.onNewPriceDataCallback = onNewPriceDataCallback
self.configurationManager = configurationManager
self._read_configuration()
self.lastData = {}
self.symbolList = []

def _read_configuration(self):
try:
self.alphaVantageAPIKey = self.configurationManager.get_alpha_vantage_api_key()
self.alphaVantageBaseURL = self.configurationManager.get_alpha_vantage_base_url()
except Exception as e:
print("LivePricesWebThread: _read_configuration() {0}".format(e))
sys.exit(1)

def task(self):
priceDict = {}
for symbol in self.symbolList:
if not self._finished.isSet():
value = self._fetch_price_data(symbol)
self._timeout.wait(1) # Wait 1 sec as suggested by AlphaVantage support
if value is not None:
priceDict[symbol] = value
if not self._finished.isSet():
self.lastData = priceDict # Store internally
self.onNewPriceDataCallback() # Notify the model

def _fetch_price_data(self, symbol):
try:
url = self._build_url("TIME_SERIES_DAILY", symbol, "5min", self.alphaVantageAPIKey)
request = urllib.request.urlopen(url, timeout=10)
content = request.read()
data = json.loads(content.decode('utf-8'))
timeSerie = data["Time Series (Daily)"]
last = next(iter(timeSerie.values()))
value = float(last["4. close"])
except Exception:
print("LivePricesWebThread: _fetch_price_data(): {0}".format(url))
value = None
return value

def _build_url(self, aLength, aSymbol, anInterval, anApiKey):
function = "function=" + aLength
symbol = "symbol=" + aSymbol
apiKey = "apikey=" + anApiKey
url = self.alphaVantageBaseURL + "?" + function + "&" + symbol + "&" + apiKey
return url

def get_last_data(self):
return self.lastData

def set_symbol_list(self, aList):
self.symbolList = aList

class Model():

def __init__(self, configurationManager):
self.configurationManager = configurationManager
self._read_configuration()
self._read_database(self.dbFilePath)
self.callbacks = {} # DataStruct containing the callbacks
self.livePricesThread = LivePricesWebThread(self.configurationManager, self.on_new_price_data, self.webPollingPeriod)
self.callbacks = {} # DataStruct containing the callbacks
self.livePricesThread = StockPriceGetter(
self.configurationManager, self.on_new_price_data, self.webPollingPeriod)
self.portfolio = Portfolio("Portfolio1")

# INTERNAL FUNCTIONS
Expand Down Expand Up @@ -139,7 +86,8 @@ def _update_portfolio(self):
self.portfolio.clear()
for symbol, amount in holdings.items():
self.portfolio.update_holding_amount(symbol, amount)
self.portfolio.update_holding_open_price(symbol, self.get_holding_open_price(symbol))
self.portfolio.update_holding_open_price(
symbol, self.get_holding_open_price(symbol))
self.portfolio.set_invested_amount(investedAmount)
self.portfolio.set_cash_available(cashAvailable)
for symbol, price in self.livePricesThread.get_last_data().items():
Expand Down Expand Up @@ -177,7 +125,8 @@ def _write_log_to_file(self, filepath):
# write the in memory db to a file
self._utils_indent_xml_tree(self.log)
newTree = ET.ElementTree(self.log)
newTree.write(filepath, xml_declaration=True, encoding='utf-8', method="xml")
newTree.write(filepath, xml_declaration=True,
encoding='utf-8', method="xml")

# Source http://effbot.org/zone/element-lib.htm#prettyprint
def _utils_indent_xml_tree(self, elem, level=0):
Expand Down Expand Up @@ -206,10 +155,14 @@ def get_log_as_list(self):
d["date"] = row.find('date').text
d["action"] = row.find('action').text
d["symbol"] = row.find('symbol').text
d["amount"] = float(row.find('amount').text) if row.find('amount').text is not None else 0
d["price"] = float(row.find('price').text) if row.find('price').text is not None else 0.0
d["fee"] = float(row.find('fee').text) if row.find('fee').text is not None else 0.0
d["stamp_duty"] = float(row.find('stamp_duty').text) if row.find('stamp_duty').text is not None else 0.0
d["amount"] = float(row.find('amount').text) if row.find(
'amount').text is not None else 0
d["price"] = float(row.find('price').text) if row.find(
'price').text is not None else 0.0
d["fee"] = float(row.find('fee').text) if row.find(
'fee').text is not None else 0.0
d["stamp_duty"] = float(row.find('stamp_duty').text) if row.find(
'stamp_duty').text is not None else 0.0
listOfEntries.append(d)
return listOfEntries

Expand All @@ -220,7 +173,7 @@ def get_holding_open_price(self, symbol):
sum = 0
count = 0
targetAmount = self.portfolio.get_holding_amount(symbol)
for row in self.log[::-1]: # reverse order
for row in self.log[::-1]: # reverse order
action = row.find("action").text
sym = row.find("symbol").text
price = float(row.find("price").text)
Expand All @@ -245,7 +198,8 @@ def get_db_filepath(self):

def start(self):
self._update_portfolio()
self.livePricesThread.set_symbol_list(self.portfolio.get_holding_symbols())
self.livePricesThread.set_symbol_list(
self.portfolio.get_holding_symbols())
self.livePricesThread.start()

def stop_application(self):
Expand All @@ -254,11 +208,12 @@ def stop_application(self):
self._write_log_to_file(self.dbFilePath)

def add_new_trade(self, newTrade):
result = {"success":True,"message":"ok"}
result = {"success": True, "message": "ok"}
try:
self._add_entry_to_db(newTrade)
self._update_portfolio()
self.livePricesThread.set_symbol_list(self.portfolio.get_holding_symbols())
self.livePricesThread.set_symbol_list(
self.portfolio.get_holding_symbols())
except Exception:
result["success"] = False
result["message"] = Messages.INVALID_OPERATION.value
Expand All @@ -268,7 +223,7 @@ def on_new_price_data(self):
priceDict = self.livePricesThread.get_last_data()
for symbol, price in priceDict.items():
self.portfolio.update_holding_last_price(symbol, price)
self.callbacks[Callbacks.UPDATE_LIVE_PRICES]() # Call callback
self.callbacks[Callbacks.UPDATE_LIVE_PRICES]() # Call callback

def set_auto_refresh(self, enabled):
self.livePricesThread.enable(enabled)
Expand All @@ -280,7 +235,7 @@ def on_manual_refresh_live_data(self):
self.livePricesThread.force_single_run()

def save_log_file(self, filepath):
result = {"success":True,"message":"ok"}
result = {"success": True, "message": "ok"}
try:
self._write_log_to_file(filepath)
except Exception:
Expand All @@ -289,7 +244,7 @@ def save_log_file(self, filepath):
return result

def open_log_file(self, filepath):
result = {"success":True,"message":"ok"}
result = {"success": True, "message": "ok"}
try:
self._reset(filepath)
except Exception:
Expand All @@ -298,12 +253,13 @@ def open_log_file(self, filepath):
return result

def delete_last_trade(self):
result = {"success":True,"message":"ok"}
result = {"success": True, "message": "ok"}
try:
self._remove_last_log_entry()
except Exception:
result["success"] = False
result["message"] = Messages.INVALID_OPERATION
self._update_portfolio()
self.livePricesThread.set_symbol_list(self.portfolio.get_holding_symbols())
self.livePricesThread.set_symbol_list(
self.portfolio.get_holding_symbols())
return result
71 changes: 71 additions & 0 deletions src/Model/StockPriceGetter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from Utils.TaskThread import TaskThread
import os
import sys
import inspect
import urllib.request
import json

currentdir = os.path.dirname(os.path.abspath(
inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)


class StockPriceGetter(TaskThread):

def __init__(self, configurationManager, onNewPriceDataCallback, updatePeriod):
TaskThread.__init__(self, updatePeriod)
self.onNewPriceDataCallback = onNewPriceDataCallback
self.configurationManager = configurationManager
self._read_configuration()
self.lastData = {}
self.symbolList = []

def _read_configuration(self):
try:
self.alphaVantageAPIKey = self.configurationManager.get_alpha_vantage_api_key()
self.alphaVantageBaseURL = self.configurationManager.get_alpha_vantage_base_url()
except Exception as e:
print("LivePricesWebThread: _read_configuration() {0}".format(e))
sys.exit(1)

def task(self):
priceDict = {}
for symbol in self.symbolList:
if not self._finished.isSet():
value = self._fetch_price_data(symbol)
# Wait 1 sec as suggested by AlphaVantage support
self._timeout.wait(1)
if value is not None:
priceDict[symbol] = value
if not self._finished.isSet():
self.lastData = priceDict # Store internally
self.onNewPriceDataCallback() # Notify the model

def _fetch_price_data(self, symbol):
try:
url = self._build_url("TIME_SERIES_DAILY",
symbol, "5min", self.alphaVantageAPIKey)
request = urllib.request.urlopen(url, timeout=10)
content = request.read()
data = json.loads(content.decode('utf-8'))
timeSerie = data["Time Series (Daily)"]
last = next(iter(timeSerie.values()))
value = float(last["4. close"])
except Exception:
print("LivePricesWebThread: _fetch_price_data(): {0}".format(url))
value = None
return value

def _build_url(self, aLength, aSymbol, anInterval, anApiKey):
function = "function=" + aLength
symbol = "symbol=" + aSymbol
apiKey = "apikey=" + anApiKey
url = self.alphaVantageBaseURL + "?" + function + "&" + symbol + "&" + apiKey
return url

def get_last_data(self):
return self.lastData

def set_symbol_list(self, aList):
self.symbolList = aList

0 comments on commit b26e5c4

Please sign in to comment.