def get_stock_intraday_info(cls, stock_symbol: str) -> list: ''' return stock intraday info as a dict retrieved from url json, key 'intraday' ''' intraday_url = cls.intraday_url + '/'.join( [cls.time_interval, stock_symbol]) params = {'apikey': cls.api_token} _intraday_trades = [] try: res = requests.get(intraday_url, params=params) if res: _intraday_trades = res.json() else: pass except requests.exceptions.ConnectionError: logger.info( f'connection error: {intraday_url} {stock_symbol} {params}') # if there is intraday info, convert date string and provide time and # create list of trade_info tuples trade_tuple = namedtuple('trade_tuple', 'date open close low high volume') intraday_trades = [] min_low = None max_high = None if _intraday_trades: date_trade = datetime.datetime.strptime( _intraday_trades[0].get('date'), "%Y-%m-%d %H:%M:%S").date() for i, _trade in enumerate(_intraday_trades): _tradetime = datetime.datetime.strptime( _trade.get('date'), "%Y-%m-%d %H:%M:%S") if _tradetime.date() != date_trade: break # adjust cumulative volumes try: volume = _trade.get('volume') - _intraday_trades[ i + 1].get('volume') if volume < 0: volume = 0 except IndexError: volume = 0 intraday_trades.append( trade_tuple( date=_tradetime, open=_trade.get('open'), close=_trade.get('close'), low=_trade.get('low'), high=_trade.get('high'), volume=volume, )) min_low = get_min(_trade.get('low'), min_low) max_high = get_max(_trade.get('high'), max_high) intraday_trades = sorted(intraday_trades, key=lambda k: k.date) # add start and end time initial_open = intraday_trades[0].open last_close = intraday_trades[-1].close start_time = intraday_trades[0].date.strftime( "%Y-%m-%d") + ' 08:00:00' intraday_trades.insert( 0, trade_tuple(date=datetime.datetime.strptime( start_time, "%Y-%m-%d %H:%M:%S"), open=None, close=None, low=None, high=None, volume=None)) end_time = intraday_trades[-1].date.strftime( "%Y-%m-%d") + ' 18:00:00' intraday_trades.append( trade_tuple( date=datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S"), open=initial_open, close=last_close, low=min_low, high=max_high, volume=None, )) else: # if not succeeded try with fallback site on marketstack intraday_trades = get_intraday_marketstack(stock_symbol) # or (last resort) try alpha vantage if not intraday_trades: intraday_trades = get_intraday_alpha_vantage(stock_symbol) return intraday_trades
def get(self, request, source, symbol): if not Stock.objects.filter(symbol=symbol): return redirect(reverse('stock_quotes')) intraday_trades = self.wtd.get_stock_intraday_info(symbol) chart_data = [] min_price, max_price, max_volume = None, None, None date_format = '%d-%m-%Y %H:%M' for trade in intraday_trades: chart_data.append([ trade.date.strftime(date_format), trade.open, trade.close, trade.low, trade.high, trade.volume, ]) min_price = get_min(trade.low, min_price) max_price = get_max(trade.high, max_price) max_volume = get_max(trade.volume, max_volume) if not min_price or not max_price: min_price, max_price = 0, 0 if not max_volume: max_volume = 0 try: initial_open = intraday_trades[1].open latest_close = intraday_trades[-2].close prc_change = 100 * (float(latest_close) - float(initial_open)) / float(initial_open) except IndexError: initial_open, latest_close, prc_change = None, None, None if initial_open and latest_close and prc_change: if abs(float(prc_change)) < 0.01: txt_color = 'txt_normal' caret = CARET_NO_CHANGE elif float(prc_change) < 0: txt_color = 'txt_red' caret = CARET_DOWN else: txt_color = 'txt_green' caret = CARET_UP subcaption = ''.join([ Stock.objects.get(symbol=symbol).currency.currency, f' {float(latest_close):.2f} ({prc_change:.1f}%)', f' {caret}' ]) else: subcaption = '' txt_color = 'txt_normal' caption = ''.join( [Stock.objects.get(symbol=symbol).company, ' (', symbol, ')']) schema = json.dumps(self.wtd.get_schema(date_format)) chart_data = json.dumps(chart_data) time_series = TimeSeries(FusionTable(schema, chart_data)) time_series.AddAttribute( 'styleDefinition', { 'txt_red': { 'fill': font_red, 'font-weight': font_weight, 'font-size': font_size }, 'txt_green': { 'fill': font_green, 'font-weight': font_weight, 'font-size': font_size }, 'txt_normal': { 'fill': font_white, 'font-weight': font_weight, 'font-size': font_size }, }) time_series.AddAttribute('chart', { 'multicanvas': '0', 'theme': chart_theme, 'showlegend': '0', }) time_series.AddAttribute('caption', { 'text': caption, }) time_series.AddAttribute('subcaption', { 'text': subcaption, 'style': { 'text': txt_color }, }) time_series.AddAttribute('navigator', {'enabled': '0'}) time_series.AddAttribute('extensions', {'customrangeselector': { 'enabled': '0' }}) time_series.AddAttribute('yaxis', [ { 'plot': [{ 'value': { 'open': 'open', 'high': 'high', 'low': 'low', 'close': 'close' }, 'type': 'candlestick' }], 'title': 'Stock Value', 'min': min_price * 0.99, 'max': max_price * 1.01, }, { 'plot': [{ 'value': 'volume', 'type': 'column' }], 'title': 'Volume', 'max': max_volume * 3, }, ]) trade_series = FusionCharts( 'timeseries', 'trades', width, height, 'chart-container', 'json', time_series, ) context = { 'chart_js': trade_series.render(), 'data_provider_url': self.data_provider_url, 'stock_symbol': symbol, 'source': source, } logger.info( f'user {request.user} [ip: {get_client_ip(request)}] is looking ' f'intraday trades for {symbol}') return render(request, self.template_name, context)
def get_stock_intraday_info(cls, stock_symbol): ''' return stock intraday info as a dict retrieved from url json, key 'intraday' ''' if alpha_vantage_enabled: return get_intraday_alpha_vantage(stock_symbol) # range: number of days (1-30), interval: in minutes params = {'symbol': stock_symbol.upper(), 'range': '1', 'interval': '5', 'sort': 'asc', 'api_token': cls.api_token} intraday_info = {} try: res = requests.get(cls.intraday_url, params=params) if res: intraday_info = res.json().get('intraday', {}) else: pass except requests.exceptions.ConnectionError: logger.info(f'connection error: {cls.intraday_url} {params}') # if there is intraday info, convert date string and provide time and # create list of trade_info tuples trade = namedtuple('trade', 'date open close low high volume') intraday_trades = [] min_low = None max_high = None if intraday_info: for time_stamp, trade_info in intraday_info.items(): intraday_trades.append( trade(date=datetime.datetime.strptime( time_stamp, "%Y-%m-%d %H:%M:%S"), open=trade_info.get('open'), close=trade_info.get('close'), low=trade_info.get('low'), high=trade_info.get('high'), volume=trade_info.get('volume'), ) ) min_low = get_min(trade_info.get('low'), min_low) max_high = get_max(trade_info.get('high'), max_high) initial_open = intraday_trades[0].open last_close = intraday_trades[-1].close # add start and end time start_time = intraday_trades[0].date.strftime("%Y-%m-%d") + ' 08:00:00' intraday_trades.insert( 0, trade(date=datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S"), open=None, close=None, low=None, high=None, volume=None )) end_time = intraday_trades[-1].date.strftime("%Y-%m-%d") + ' 18:00:00' intraday_trades.append( trade(date=datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S"), open=initial_open, close=last_close, low=min_low, high=max_high, volume=None, )) else: logger.info(f'unable to get stock intraday data for ' f'{cls.intraday_url} {params}') return intraday_trades
def get(self, request, source, symbol, period): if period not in periods: return redirect(reverse('stock_quotes')) elif period == 'max': period = '1000' if not Stock.objects.filter(symbol=symbol): return redirect(reverse('stock_quotes')) history_trades = self.wtd.get_stock_history_info(symbol) if history_trades: start_period = history_trades[0].date -\ datetime.timedelta(days=int(period) * 365) chart_data = [] min_price, max_price, max_volume = None, None, None date_format = '%d-%m-%Y' for trade in history_trades: if trade.date > start_period: chart_data.append([ trade.date.strftime(date_format), trade.open, trade.close, trade.low, trade.high, trade.volume, ]) min_price = get_min(trade.low, min_price) max_price = get_max(trade.high, max_price) max_volume = get_max(trade.volume, max_volume) if not min_price or not max_price: min_price, max_price = 0, 0 start_date, end_date = '01-01-1900', '01-01-1900' else: end_date = history_trades[0].date start_date = end_date - datetime.timedelta(days=365) start_date = start_date.strftime(date_format) end_date = end_date.strftime(date_format) if not max_volume: max_volume = 0 subcaption = '' caption = ''.join( [Stock.objects.get(symbol=symbol).company, ' (', symbol, ')']) schema = json.dumps(self.wtd.get_schema(date_format)) chart_data = json.dumps(chart_data) time_series = TimeSeries(FusionTable(schema, chart_data)) time_series.AddAttribute('chart', { 'multicanvas': '0', 'theme': chart_theme, 'showlegend': '0', }) time_series.AddAttribute('caption', { 'text': caption, }) time_series.AddAttribute('subcaption', { 'text': subcaption, }) time_series.AddAttribute( 'navigator', {'enabled': '1'}, ) time_series.AddAttribute('extensions', {'customrangeselector': { 'enabled': '1' }}) time_series.AddAttribute( 'xaxis', {'initialinterval': { 'from': start_date, 'to': end_date }}) time_series.AddAttribute('yaxis', [ { 'plot': [{ 'value': { 'open': 'open', 'high': 'high', 'low': 'low', 'close': 'close' }, 'type': 'candlestick' }], 'title': 'Stock Value (' + Stock.objects.get(symbol=symbol).currency.currency + ')', 'min': min_price * 0.99, 'max': max_price * 1.01, }, { 'plot': [{ 'value': 'volume', 'type': 'column' }], 'title': 'Volume', 'max': max_volume * 3, }, ]) trade_series = FusionCharts( 'timeseries', 'trades', width, height, 'chart-container', 'json', time_series, ) context = { 'chart_js': trade_series.render(), 'data_provider_url': self.data_provider_url, 'stock_symbol': symbol, 'source': source, } logger.info( f'user {request.user} [ip: {get_client_ip(request)}] is looking ' f'historic trades for {symbol}') return render(request, self.template_name, context)
def get_intraday_alpha_vantage(symbol): symbol = symbol.upper() params = { 'symbol': symbol, 'function': 'TIME_SERIES_INTRADAY', 'interval': '5min', 'apikey': api_token } meta_data = {} time_series = {} try: res = requests.get(alpha_vantage_api_url, params=params) if res: meta_data = res.json().get('Meta Data', {}) time_series = res.json().get('Time Series (5min)', {}) except requests.exceptions.ConnectionError: logger.info(f'connection error: {alpha_vantage_api_url} {params}') if not meta_data or not time_series: return [] try: stock_db = Stock.objects.get(symbol=symbol) except Stock.DoesNotExist: return [] timezone_stock = convert_timezone(stock_db.exchange.time_zone_name.upper()) timezone_EST = 'EST' trade_tuple = namedtuple('trade', 'date open close low high volume') intraday_trades = [] min_low = None max_high = None last_trade = datetime.datetime.strptime( meta_data.get('3. Last Refreshed'), '%Y-%m-%d %H:%M:%S').replace( tzinfo=pytz.timezone(timezone_EST)).astimezone( pytz.timezone(timezone_stock)) for time_stamp, trade_info in time_series.items(): time_stamp = datetime.datetime.strptime( time_stamp, '%Y-%m-%d %H:%M:%S').replace( tzinfo=pytz.timezone(timezone_EST)).astimezone( pytz.timezone(timezone_stock)) if time_stamp.date() == last_trade.date(): trade = trade_tuple( date=time_stamp.replace(tzinfo=None), open=trade_info.get('1. open'), high=trade_info.get('2. high'), low=trade_info.get('3. low'), close=trade_info.get('4. close'), volume=trade_info.get('5. volume'), ) intraday_trades.append(trade) min_low = get_min(trade.low, min_low) max_high = get_max(trade.high, max_high) # reverse sorting on timestamp intraday_trades = sorted(intraday_trades, key=lambda k: k.date) # add start and end time initial_open = intraday_trades[0].open last_close = intraday_trades[-1].close start_time = intraday_trades[0].date.strftime("%Y-%m-%d") + ' 08:00:00' intraday_trades.insert( 0, trade_tuple(date=datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S"), open=None, close=None, low=None, high=None, volume=None)) end_time = intraday_trades[-1].date.strftime("%Y-%m-%d") + ' 18:00:00' intraday_trades.append( trade_tuple( date=datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S"), open=initial_open, close=last_close, low=min_low, high=max_high, volume=None, )) return intraday_trades