1from datetime import datetime, timedelta, date 2 3from AnyQt.QtCore import QDate 4from AnyQt.QtWidgets import QDateEdit, QComboBox 5 6from Orange.widgets import widget, gui, settings 7from Orange.widgets.widget import Output 8 9from orangecontrib.timeseries import Timeseries 10from orangecontrib.timeseries.datasources import finance_data 11 12 13class OWYahooFinance(widget.OWWidget): 14 name = 'Yahoo Finance' 15 description = "Generate time series from Yahoo Finance stock market data." 16 icon = 'icons/YahooFinance.svg' 17 priority = 9 18 19 class Outputs: 20 time_series = Output("Time series", Timeseries) 21 22 QT_DATE_FORMAT = 'yyyy-MM-dd' 23 PY_DATE_FORMAT = '%Y-%m-%d' 24 MIN_DATE = date(1851, 1, 1) 25 26 date_from = settings.Setting( 27 (datetime.now().date() - timedelta(5 * 365)).strftime(PY_DATE_FORMAT)) 28 date_to = settings.Setting(datetime.now().date().strftime(PY_DATE_FORMAT)) 29 symbols = settings.Setting(['AMZN', 'AAPL', 'GOOG', 'FB', 'SPY', '^DJI', '^TNX']) 30 31 want_main_area = False 32 resizing_enabled = False 33 34 class Error(widget.OWWidget.Error): 35 download_error = widget.Msg('Failed to download data (HTTP Error {}). ' 36 'Wrong stock symbol?') 37 38 def __init__(self): 39 box = gui.widgetBox(self.controlArea, 'Yahoo Finance Stock Data', 40 orientation='horizontal') 41 lbox = gui.widgetBox(box, orientation='vertical') 42 hbox = gui.widgetBox(lbox, orientation='horizontal') 43 gui.label(hbox, self, 'Ticker:') 44 self.combo = combo = QComboBox(editable=True, 45 insertPolicy=QComboBox.InsertAtTop) 46 combo.addItems(self.symbols) 47 hbox.layout().addWidget(combo) 48 # combo = gui.comboBox( 49 # lbox, self, 'symbol',#, items=self.symbols, 50 # label='Ticker:', orientation='horizontal', 51 # editable=True, maximumContentsLength=-1) 52 gui.rubber(combo.parentWidget()) 53 minDate = QDate.fromString(self.MIN_DATE.strftime(self.PY_DATE_FORMAT), 54 self.QT_DATE_FORMAT) 55 date_from = QDateEdit( 56 QDate.fromString(self.date_from, self.QT_DATE_FORMAT), 57 displayFormat=self.QT_DATE_FORMAT, 58 minimumDate=minDate, 59 calendarPopup=True) 60 date_to = QDateEdit( 61 QDate.fromString(self.date_to, self.QT_DATE_FORMAT), 62 displayFormat=self.QT_DATE_FORMAT, 63 minimumDate=minDate, 64 calendarPopup=True) 65 date_from.dateChanged.connect( 66 lambda date: setattr(self, 'date_from', 67 date.toString(self.QT_DATE_FORMAT))) 68 date_to.dateChanged.connect( 69 lambda date: setattr(self, 'date_to', 70 date.toString(self.QT_DATE_FORMAT))) 71 hbox = gui.hBox(lbox) 72 gui.label(hbox, self, "From:") 73 hbox.layout().addWidget(date_from) 74 hbox = gui.hBox(lbox) 75 gui.label(hbox, self, "To:") 76 hbox.layout().addWidget(date_to) 77 78 self.button = gui.button(self.controlArea, self, 'Download', 79 callback=self.download) 80 81 def download(self): 82 date_from = datetime.strptime(self.date_from, self.PY_DATE_FORMAT) 83 date_to = datetime.strptime(self.date_to, self.PY_DATE_FORMAT) 84 85 # Update symbol in symbols history 86 symbol = self.combo.currentText().strip().upper() 87 self.combo.removeItem(self.combo.currentIndex()) 88 self.combo.insertItem(0, symbol) 89 self.combo.setCurrentIndex(0) 90 try: 91 self.symbols.remove(symbol) 92 except ValueError: 93 pass 94 self.symbols.insert(0, symbol) 95 96 if not symbol: 97 return 98 99 self.Error.clear() 100 with self.progressBar(3) as progress: 101 try: 102 progress.advance() 103 self.button.setDisabled(True) 104 data = finance_data(symbol, date_from, date_to) 105 106 self.Outputs.time_series.send(data) 107 except Exception as e: 108 self.Error.download_error(getattr(e, 'status', -1)) 109 finally: 110 self.button.setDisabled(False) 111 112 113if __name__ == "__main__": 114 from AnyQt.QtWidgets import QApplication 115 116 a = QApplication([]) 117 ow = OWYahooFinance() 118 119 ow.show() 120 a.exec() 121