import seaborn as sns from sklearn.ensemble import RandomForestRegressor from sklearn.linear_model import LinearRegression from sklearn.neighbors import KNeighborsRegressor from sklearn.neural_network import MLPRegressor from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error from alpha_vantage.timeseries import TimeSeries # current evaluation is for Chevron ts = TimeSeries(key=av_key, output_format='pandas') cvx, info_cvx = ts.get_daily_adjusted('CVX', outputsize='full') cvx = cvx.reset_index() # adding on basic historical trends, previous work has shown that this is a good start to a stock estimator def historical_trends(df): target = '5. adjusted close' df = df.sort_values('date') df['mean_5'] = df[target].rolling(window=5).mean().shift() df['mean_30'] = df[target].rolling(window=30).mean().shift() df['mean_365'] = df[target].rolling(window=365).mean().shift() df['std_5'] = df[target].rolling(window=5).std().shift() df['std_30'] = df[target].rolling(window=30).std().shift()
class StockInfo: def __init__(self, ticker, buy_date, initial_investment): self.ticker = ticker self.stock_data_file = f'AdvancedSimulator/IntermediateData/{self.ticker}.json' print(self.stock_data_file) self.ts = TimeSeries(key='INSERT_HERE', output_format='pandas') # TODO: Add key config self.data_downloaded = False self.download_data() self.initial_value = initial_investment self.holdings_value = initial_investment self.buy_price = self.get_opening_price(buy_date) self.last_day_price = self.buy_price def get_return(self): rtn = self.last_day_price / self.buy_price - 1 # This is the return rate return rtn def update_holdings_value(self, new_value): self.holdings_value = new_value def update_last_price(self, new_last_price): self.last_day_price = new_last_price def download_data(self, force=False): if force or not os.path.isfile(self.stock_data_file): raw_data = self.ts.get_daily_adjusted(symbol=self.ticker, outputsize='full')[0] print(type(raw_data)) raw_data.to_json(path_or_buf=self.stock_data_file, orient='index') self.data_downloaded = True def get_data(self): if self.data_downloaded: data = pd.read_json(path_or_buf=self.stock_data_file, orient='index', typ='frame') return data else: raise "The file doesn't exists so download failed somehow" # Get closing price if possible def get_opening_price(self, date): return self.get_price(date, '1. open') # Get closing price if possible def get_closing_price(self, date): return self.get_price(date, '5. adjusted close') # Get closing price if possible def get_high_price(self, date): return self.get_price(date, '2. high') # Get closing price if possible def get_low_price(self, date): return self.get_price(date, '3. low') def get_price(self, date, key): date_string = date.strftime('%Y-%m-%d') data = self.get_data() adjusted_close = data[key] data_point = adjusted_close.get(date_string) if len(data_point) == 0: return None closing_price = float(data_point[[0]]) return closing_price
from alpha_vantage.timeseries import TimeSeries import matplotlib.pyplot as plt import numpy as np import pandas as pd ts = TimeSeries(key='N0D53X82CSFYKDIB', output_format='pandas') ##Pegando as informações dos papeis ITUB4, metadata = ts.get_daily_adjusted('ITUB4.SA',outputsize='full') PETR4, metadata = ts.get_daily_adjusted('PETR4.SA',outputsize='full') ABEV3, metadata = ts.get_daily_adjusted('ABEV3.SA',outputsize='full') VALE3, metadata = ts.get_daily_adjusted('VALE3.SA',outputsize='full') #invertendo a ordem para do mais antigo para o mais novo ITUB4 = ITUB4.iloc[::-1] PETR4 = PETR4.iloc[::-1] ABEV3 = ABEV3.iloc[::-1] VALE3 = VALE3.iloc[::-1] mydata = pd.DataFrame() ##selecionando apenas o fechamento ajustado mydata['ITUB4'] = ITUB4['5. adjusted close'] mydata['PETR4'] = PETR4['5. adjusted close'] mydata['ABEV3'] = ABEV3['5. adjusted close'] mydata['VALE3'] = VALE3['5. adjusted close'] #Usando o iloc para indexar a partir da primeira data
def load( ticker: str, start: datetime = (datetime.now() - timedelta(days=1100)), interval: int = 1440, end: datetime = datetime.now(), prepost: bool = False, source: str = "yf", iexrange: str = "ytd", weekly: bool = False, monthly: bool = False, ): """ Load a symbol to perform analysis using the string above as a template. Optional arguments and their descriptions are listed above. The default source is, yFinance (https://pypi.org/project/yfinance/). Alternatively, one may select either AlphaVantage (https://www.alphavantage.co/documentation/) or IEX Cloud (https://iexcloud.io/docs/api/) as the data source for the analysis. Please note that certain analytical features are exclusive to the source. To load a symbol from an exchange outside of the NYSE/NASDAQ default, use yFinance as the source and add the corresponding exchange to the end of the symbol. i.e. ‘BNS.TO’. BNS is a dual-listed stock, there are separate options chains and order books for each listing. Opportunities for arbitrage may arise from momentary pricing discrepancies between listings with a dynamic exchange rate as a second order opportunity in ForEx spreads. Find the full list of supported exchanges here: https://help.yahoo.com/kb/exchanges-data-providers-yahoo-finance-sln2310.html Certain analytical features, such as VWAP, require the ticker to be loaded as intraday using the ‘-i x’ argument. When encountering this error, simply reload the symbol using the interval argument. i.e. ‘load -t BNS -s YYYY-MM-DD -i 1 -p’ loads one-minute intervals, including Pre/After Market data, using the default source, yFinance. Certain features, such as the Prediction menu, require the symbol to be loaded as daily and not intraday. Parameters ---------- ticker: str Ticker to get data start: datetime Start date to get data from with interval: int Interval (in minutes) to get data 1, 5, 15, 30, 60 or 1440 end: datetime End date to get data from with prepost: bool Pre and After hours data source: str Source of data extracted iexrange: str Timeframe to get IEX data. weekly: bool Flag to get weekly data monthly: bool Flag to get monthly data Returns ------- df_stock_candidate: pd.DataFrame Dataframe of data """ # Daily if interval == 1440: # Alpha Vantage Source if source == "av": try: ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") # pylint: disable=unbalanced-tuple-unpacking df_stock_candidate, _ = ts.get_daily_adjusted( symbol=ticker, outputsize="full" ) except Exception as e: console.print(e) return pd.DataFrame() df_stock_candidate.columns = [ val.split(". ")[1].capitalize() for val in df_stock_candidate.columns ] df_stock_candidate = df_stock_candidate.rename( columns={ "Adjusted close": "Adj Close", } ) # Check that loading a stock was not successful # pylint: disable=no-member if df_stock_candidate.empty: console.print("No data found.\n") return pd.DataFrame() df_stock_candidate.index = df_stock_candidate.index.tz_localize(None) # pylint: disable=no-member df_stock_candidate.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected df_stock_candidate = df_stock_candidate[ (df_stock_candidate.index >= start.strftime("%Y-%m-%d")) & (df_stock_candidate.index <= end.strftime("%Y-%m-%d")) ] # Yahoo Finance Source elif source == "yf": # TODO: Better handling of interval with week/month int_ = "1d" int_string = "Daily" if weekly: int_ = "1wk" int_string = "Weekly" if monthly: int_ = "1mo" int_string = "Monthly" # Adding a dropna for weekly and monthly because these include weird NaN columns. df_stock_candidate = yf.download( ticker, start=start, end=end, progress=False, interval=int_ ).dropna(axis=0) # Check that loading a stock was not successful if df_stock_candidate.empty: console.print("") return pd.DataFrame() df_stock_candidate.index.name = "date" # IEX Cloud Source elif source == "iex": df_stock_candidate = pd.DataFrame() try: client = pyEX.Client(api_token=cfg.API_IEX_TOKEN, version="v1") df_stock_candidate = client.chartDF(ticker, timeframe=iexrange) # Check that loading a stock was not successful if df_stock_candidate.empty: console.print("No data found.\n") except Exception as e: if "The API key provided is not valid" in str(e): console.print("[red]Invalid API Key[/red]\n") else: console.print(e) return df_stock_candidate df_stock_candidate = df_stock_candidate[ ["close", "fHigh", "fLow", "fOpen", "fClose", "volume"] ] df_stock_candidate = df_stock_candidate.rename( columns={ "close": "Close", "fHigh": "High", "fLow": "Low", "fOpen": "Open", "fClose": "Adj Close", "volume": "Volume", } ) df_stock_candidate.sort_index(ascending=True, inplace=True) s_start = df_stock_candidate.index[0] s_interval = f"{interval}min" int_string = "Daily" if interval == 1440 else "Intraday" else: s_int = str(interval) + "m" s_interval = s_int + "in" d_granularity = {"1m": 6, "5m": 59, "15m": 59, "30m": 59, "60m": 729} s_start_dt = datetime.utcnow() - timedelta(days=d_granularity[s_int]) s_date_start = s_start_dt.strftime("%Y-%m-%d") df_stock_candidate = yf.download( ticker, start=s_date_start if s_start_dt > start else start.strftime("%Y-%m-%d"), progress=False, interval=s_int, prepost=prepost, ) # Check that loading a stock was not successful if df_stock_candidate.empty: console.print("") return pd.DataFrame() df_stock_candidate.index = df_stock_candidate.index.tz_localize(None) if s_start_dt > start: s_start = pytz.utc.localize(s_start_dt) else: s_start = start df_stock_candidate.index.name = "date" int_string = "Intraday" s_intraday = (f"Intraday {s_interval}", int_string)[interval == 1440] console.print( f"\nLoading {s_intraday} {ticker.upper()} stock " f"with starting period {s_start.strftime('%Y-%m-%d')} for analysis.", ) return df_stock_candidate
def load(l_args, s_ticker, s_start, s_interval, df_stock): parser = argparse.ArgumentParser( add_help=False, prog="load", description= "Load stock ticker to perform analysis on. When the data source is 'yf', an Indian ticker can be" " loaded by using '.NS' at the end, e.g. 'SBIN.NS'. See available market in" " https://help.yahoo.com/kb/exchanges-data-providers-yahoo-finance-sln2310.html.", ) parser.add_argument( "-t", "--ticker", action="store", dest="s_ticker", required=True, help="Stock ticker", ) parser.add_argument( "-s", "--start", type=valid_date, default="2015-01-01", dest="s_start_date", help="The starting date (format YYYY-MM-DD) of the stock", ) parser.add_argument( "-i", "--interval", action="store", dest="n_interval", type=int, default=1440, choices=[1, 5, 15, 30, 60], help="Intraday stock minutes", ) parser.add_argument( "--source", action="store", dest="source", type=check_sources, default="yf", help="Source of historical data. 'yf' and 'av' available.", ) parser.add_argument( "-p", "--prepost", action="store_true", default=False, dest="b_prepost", help= "Pre/After market hours. Only works for 'yf' source, and intraday data", ) try: # For the case where a user uses: 'load BB' if l_args: if "-" not in l_args[0]: l_args.insert(0, "-t") ns_parser = parse_known_args_and_warn(parser, l_args) if not ns_parser: return [s_ticker, s_start, s_interval, df_stock] # Daily if ns_parser.n_interval == 1440: # Alpha Vantage Source if ns_parser.source == "av": ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") # pylint: disable=unbalanced-tuple-unpacking df_stock_candidate, _ = ts.get_daily_adjusted( symbol=ns_parser.s_ticker, outputsize="full") # Check that loading a stock was not successful if df_stock_candidate.empty: print("") return [s_ticker, s_start, s_interval, df_stock] # pylint: disable=no-member df_stock_candidate.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected df_stock_candidate = df_stock_candidate[ns_parser. s_start_date:] # Yahoo Finance Source elif ns_parser.source == "yf": df_stock_candidate = yf.download(ns_parser.s_ticker, start=ns_parser.s_start_date, progress=False) # Check that loading a stock was not successful if df_stock_candidate.empty: print("") return [s_ticker, s_start, s_interval, df_stock] df_stock_candidate = df_stock_candidate.rename( columns={ "Open": "1. open", "High": "2. high", "Low": "3. low", "Close": "4. close", "Adj Close": "5. adjusted close", "Volume": "6. volume", }) df_stock_candidate.index.name = "date" # Check if start time from dataframe is more recent than specified if df_stock_candidate.index[0] > pd.to_datetime( ns_parser.s_start_date): s_start = df_stock_candidate.index[0] else: s_start = ns_parser.s_start_date # Intraday else: # Alpha Vantage Source if ns_parser.source == "av": ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") # pylint: disable=unbalanced-tuple-unpacking df_stock_candidate, _ = ts.get_intraday( symbol=ns_parser.s_ticker, outputsize="full", interval=str(ns_parser.n_interval) + "min", ) # Check that loading a stock was not successful if df_stock_candidate.empty: print("") return [s_ticker, s_start, s_interval, df_stock] # pylint: disable=no-member df_stock_candidate.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected df_stock_candidate = df_stock_candidate[ns_parser. s_start_date:] # Check if start time from dataframe is more recent than specified if df_stock_candidate.index[0] > pd.to_datetime( ns_parser.s_start_date): s_start = df_stock_candidate.index[0] else: s_start = ns_parser.s_start_date # Yahoo Finance Source elif ns_parser.source == "yf": s_int = str(ns_parser.n_interval) + "m" d_granularity = { "1m": 6, "5m": 59, "15m": 59, "30m": 59, "60m": 729 } s_start_dt = datetime.utcnow() - timedelta( days=d_granularity[s_int]) s_date_start = s_start_dt.strftime("%Y-%m-%d") if s_start_dt > ns_parser.s_start_date: # Using Yahoo Finance with granularity {s_int} the starting date is set to: {s_date_start} df_stock_candidate = yf.download( ns_parser.s_ticker, start=s_date_start, progress=False, interval=s_int, prepost=ns_parser.b_prepost, ) else: df_stock_candidate = yf.download( ns_parser.s_ticker, start=ns_parser.s_start_date.strftime("%Y-%m-%d"), progress=False, interval=s_int, prepost=ns_parser.b_prepost, ) # Check that loading a stock was not successful if df_stock_candidate.empty: print("") return [s_ticker, s_start, s_interval, df_stock] if s_start_dt > ns_parser.s_start_date: s_start = pytz.utc.localize(s_start_dt) else: s_start = ns_parser.s_start_date df_stock_candidate = df_stock_candidate.rename( columns={ "Open": "1. open", "High": "2. high", "Low": "3. low", "Close": "4. close", "Adj Close": "5. adjusted close", "Volume": "6. volume", }) df_stock_candidate.index.name = "date" s_intraday = (f"Intraday {s_interval}", "Daily")[ns_parser.n_interval == 1440] print( f"Loading {s_intraday} {ns_parser.s_ticker.upper()} stock " f"with starting period {s_start.strftime('%Y-%m-%d')} for analysis.\n" ) return [ ns_parser.s_ticker.upper(), s_start, str(ns_parser.n_interval) + "min", df_stock_candidate, ] except Exception as e: print(e, "\nEither the ticker or the API_KEY are invalids. Try again!\n") return [s_ticker, s_start, s_interval, df_stock] except SystemExit: print("") return [s_ticker, s_start, s_interval, df_stock]
class UsaMarket(StockMarket): def __init__(self, provider_url=Utility.get_config( Market.US).stock_list_provider, exchanges=Utility.get_config(Market.US).exchanges, concurrent=Utility.get_config(Market.US).concurrent, retry=Utility.get_config().data_retry, stock_providers=Utility.get_config(Market.US).stock_providers, avkey=None, qkey=None): super(UsaMarket, self).__init__(Market.US) self.logger = logging.getLogger(__name__) self.provider_url = provider_url self.exchanges = exchanges self.concurrent = concurrent self.av_semaphore = BoundedSemaphore( value=1) # 1 QPS for AlphaVantange download self.retry = retry self.data_sources = [] for provider in stock_providers: if provider == 'av' and avkey is not None: self.concurrent = 1 # reset concurrent to 1 as av allows 1QPS only self.alpha_vantage = TimeSeries(key=avkey, retries=retry, output_format='pandas', indexing_type='date') self.data_sources.append(self._download_AlphaVantage) elif provider == 'morningstar': self.data_sources.append(self._download_morningstar) elif provider == 'quandl': self.data_sources.append(self._download_quandl) elif provider == 'iex': self.data_sources.append(self._download_iex) self.qkey = qkey def refresh_listing(self, excel_file=Utility.get_stock_listing_xlsx(Market.US)): """ refresh symbols lists from source provider, and store in sto :param excel_file: file name to the stored file, actual file name will append _yyyy-mm-dd.xlsx :return: void """ try: with pandas.ExcelWriter(excel_file) as writer: self.logger.info('Saving stock listings to %s.', excel_file) for exchange in self.exchanges: try: listings = pandas.read_csv(self.provider_url % exchange) # normalize the listing fields listings.rename(columns={ 'Symbol': ListingField.Symbol.value, 'IPOyear': ListingField.IPO.value, 'Sector': ListingField.Sector.value, 'industry': ListingField.Industry.value, }, index=str, inplace=True) listings.to_excel(writer, exchange) self.logger.info( 'Saved stock listings for exchange %s.', exchange.upper()) except Exception as e: self.logger.error( 'Fetching stock listings error for exchange %s: %s', exchange.upper(), e) except Exception as e: self.logger.exception('Saving stock listings failed: %s', e) def refresh_stocks(self, stock_list: [] = []): """ Refresh stock price history. It will first get latest symbols list from the web services provided in configs, then fetch stock price history from Yahoo! and Google, Yahoo! data take precedence over Google data. The data will store in the target location specified in configs. Each symbol stored in one file, naming as %exchange%_%symbol%.csv Errors are logged in error.log file. :return: None """ total_symbols = 0 symbols_no_data = 0 symbol_pattern = re.compile(r'^(\w|\.)+$') futures = [] # purge stock history folder if refresh all (ie. stock_list is empty) if not stock_list: shutil.rmtree(Utility.get_data_folder(DataFolder.Stock_History, Market.US), ignore_errors=True) # concurrent download prices with concurrent.futures.ThreadPoolExecutor( max_workers=self.concurrent) as executor: with pandas.ExcelFile( Utility.get_stock_listing_xlsx(Market.US, latest=True)) as listings: for exchange in listings.sheet_names: self.logger.info( 'Fetching stock history prices from exchange %s.', exchange.upper()) stocks = pandas.read_excel(listings, exchange) for stock in stocks.itertuples(): if stock_list and stock.Symbol not in stock_list: continue # skip stock that is not in stock_list if not symbol_pattern.match(stock.Symbol): continue # skip invalid symbols if isinstance(stock.IPO, str): start_date = Utility.get_config( ).history_start_date if stock.IPO == 'n/a' else stock.IPO elif np.isnan(stock.IPO): start_date = Utility.get_config( ).history_start_date else: start_date = str(int(stock.IPO)) start_date = pandas.to_datetime(start_date) futures.append( executor.submit(self.refresh_stock, stock.Symbol, start_date)) total_symbols += 1 for future in futures: symbols_no_data += (future.result() is None) self.logger. \ error('Stock prices update completed, %s (%s) symbols has no data.', symbols_no_data, total_symbols) def refresh_stock(self, symbol: str, start: datetime, end=datetime.datetime.today()): data = None for download_source in self.data_sources: data = download_source(symbol, start, end) if data is not None: data.sort_index(inplace=True) data.to_csv( Utility.get_stock_price_history_file(Market.US, symbol)) self.logger.info( 'Updated price history for [%s]\t(%s - %s) from %s', symbol, start.date(), end.date(), download_source.__name__) break return data def refresh_index(self, index): if not isinstance(index, UsaIndex): return self.refresh_stock(index, datetime.datetime(1982, 1, 1)) data = None if UsaIndex.SP500 == index: data = self._download_stooq('^SPX', datetime.datetime(1982, 1, 1), datetime.datetime.today()) elif UsaIndex.VIX == index: data = self._download_AlphaVantage('^VIX', datetime.datetime(1982, 1, 1), datetime.datetime.today()) if data is not None: del data[StockPriceField.Volume.value] if data is not None: data.sort_index(inplace=True) data.to_csv( Utility.get_stock_price_history_file(Market.US, index.name)) self.logger.info('Updated index [%s] history', index.name) return data def _download_AlphaVantage(self, symbol: str, start, end) -> pd.DataFrame: data = None try: with self.av_semaphore: data = self.alpha_vantage.get_daily_adjusted( symbol, outputsize='full')[0] data = data[[ '1. open', '2. high', '3. low', '5. adjusted close', '6. volume' ]] data.index.rename(StockPriceField.Date.value, inplace=True) data[StockPriceField.Symbol.value] = symbol.strip() data.rename(columns={ 'Symbol': StockPriceField.Symbol.value, '1. open': StockPriceField.Open.value, '2. high': StockPriceField.High.value, '3. low': StockPriceField.Low.value, '5. adjusted close': StockPriceField.Close.value, '6. volume': StockPriceField.Volume.value }, inplace=True) except Exception as e: self.logger.error( "Failed to get (%s) price history from AlphaVantage, %s", symbol, e) return data def _download_morningstar(self, symbol: str, start: datetime.datetime, end: datetime.datetime) -> pd.DataFrame: data = None try: # TODO: pandas.DataReader-0.6.0 would stack overflow when retry_count>0 for morningstar download, # TODO: reset after pandas.DataReader fix the issue data = web.DataReader(symbol.strip(), 'morningstar', start, end + datetime.timedelta(days=1), retry_count=0) data.reset_index(level=[0], inplace=True) data.index.rename(StockPriceField.Date.value, inplace=True) data.rename(columns={ 'Symbol': StockPriceField.Symbol.value, 'Open': StockPriceField.Open.value, 'High': StockPriceField.High.value, 'Low': StockPriceField.Low.value, 'Close': StockPriceField.Close.value, 'Volume': StockPriceField.Volume.value }, inplace=True) except Exception as e: self.logger.error( "Failed to get (%s) price history from morningstar, %s", symbol, e) return data def _download_iex(self, symbol: str, start: datetime.datetime, end: datetime.datetime) -> pd.DataFrame: data = None try: earliest = datetime.datetime.today() - relativedelta(years=5) start = max(earliest, start) end = max(earliest, end) data = web.DataReader(symbol.strip(), 'iex', start, end, retry_count=self.retry) # data.reset_index(level=[0], inplace=True) data.index.rename(StockPriceField.Date.value, inplace=True) data[StockPriceField.Symbol.value] = symbol.strip() data.rename(columns={ 'open': StockPriceField.Open.value, 'high': StockPriceField.High.value, 'low': StockPriceField.Low.value, 'close': StockPriceField.Close.value, 'volume': StockPriceField.Volume.value }, inplace=True) except Exception as e: self.logger.error("Failed to get (%s) price history from iex, %s", symbol, e) return data def _download_quandl(self, symbol: str, start: datetime.datetime, end: datetime.datetime) -> pd.DataFrame: data = None try: data = web.DataReader('WIKI/%s' % symbol.strip(), 'quandl', start, end + datetime.timedelta(days=1), retry_count=self.retry, access_key=self.qkey) data = data[[ 'AdjOpen', 'AdjHigh', 'AdjLow', 'AdjClose', 'AdjVolume' ]] data.index.rename(StockPriceField.Date.value, inplace=True) data[StockPriceField.Symbol.value] = symbol.strip() data.rename(columns={ 'AdjOpen': StockPriceField.Open.value, 'AdjHigh': StockPriceField.High.value, 'AdjLow': StockPriceField.Low.value, 'AdjClose': StockPriceField.Close.value, 'AdjVolume': StockPriceField.Volume.value }, inplace=True) except Exception as e: self.logger.error( "Failed to get (%s) price history from quandl, %s", symbol, e) return data def _download_stooq(self, symbol: str, start: datetime.datetime, end: datetime.datetime) -> pd.DataFrame: data = None try: data = web.DataReader(symbol, 'stooq', start, end + datetime.timedelta(days=1), retry_count=self.retry) data = data[['Open', 'High', 'Low', 'Close', 'Volume']] data.index.rename(StockPriceField.Date.value, inplace=True) data[StockPriceField.Symbol.value] = symbol data.rename(columns={ 'Open': StockPriceField.Open.value, 'High': StockPriceField.High.value, 'Low': StockPriceField.Low.value, 'Close': StockPriceField.Close.value, 'Volume': StockPriceField.Volume.value }, inplace=True) except Exception as e: self.logger.error( "Failed to get (%s) price history from stooq, %s", symbol, e) return data
def getDailyTimeSeries(ticker, output='compact'): dailyts = TimeSeries(key=current_app.config['ALPHA_VANTAGE_KEY'], output_format='pandas') tsdata, metadata = dailyts.get_daily_adjusted(ticker, outputsize=output) tsdata['date_time'] = tsdata.index return tsdata, metadata
# Handling Historical Input------------------------------------------ market = ["DJI", "MSFT"] marketstart = '09:31:00' marketstop = '16:00:00' #USA eastern time by default (GMT -5), 9:30AM opens, 4PM closes, Weekend closes #if historical is true, it will fetch ALL data past 20 years for every stock in the market #--------------------------- historical = True #--------------------------- if historical == True: print("fetching historical data") print("will fetch the following stocks: {}".format(str(market))) for stocks in market: data, meta_data = ts.get_daily_adjusted(stocks, outputsize='full') f = open( "{}\\Input_CSV\\Historical\\{}.txt".format( os.path.dirname(__file__), str(stocks)), 'w') for days in data: currentday = data[days] # Use this if viewer friendly text is needed #currentline = "0. day: {}\t1. open: {}\t2. high: {}\t3. low: {}\t4. close: {}\t5. adjusted close: {}\t6. volume: {}\t7. dividend amount: {}\t8. split coefficient: {}\n" #Use this if CSV version is needed currentline = "{},{},{},{},{},{},{},{},{}\n" currentline = currentline.format( days, currentday["1. open"], currentday["2. high"],
class DataManager: """ Provides an interface for interacting with the database files. Supports fetching data from AlphaVantage (the data provider), writing it to the database and querying the database in pure SQLite. Example usage: ----------------------- >>> import hedgehog.database as db >>> from pprint import pprint >>> m = db.DataManager("data//databases//daily.db") >>> results = m.query_db("SELECT * FROM prices WHERE symbol=? ORDER BY time", ("MSFT",)) >>> pprint(results) ('MSFT', 1591074000.0, 184.25, 185.0, 181.35, 184.91, 30794585), ('MSFT', 1591160400.0, 184.815, 185.94, 183.58, 185.36, 27311016), ('MSFT', 1591246800.0, 184.3, 185.84, 182.3, 182.92, 28659255), ('MSFT', 1591333200.0, 182.62, 187.73, 182.01, 187.2, 39778315) """ def __init__(self, db_path, schema_path=None): """ Connects the DataManager object to a database. If the database file does not exist, it creates the file. If a schema_path argument is provided (as a string), the connection object executes the schema. """ self.time_series = TimeSeries(config.AV_KEY, output_format="pandas") self.changes = [] self.connection = sqlite3.connect(db_path) # execute schema: if schema_path is not None: with open(schema_path) as schema: self.connection.executescript(schema.read()) def get_changes(self): """Returns all new fetched rows as an array.""" return self.changes def parse_changes_from_df(self, symbol, data_frame): """ Parses a symbol DataFrame and appends rows that are not yet in the database to self.changes. """ new_rows = 0 # Grab the row from last_unix_time where the symbol matches. There should only be one row # per symbol. The second element is the UTC time at which the symbol was last modified. If # an empty tuple is returned, we treat last modified date as UTC time 0. row = self.query_db("SELECT * FROM last_updated WHERE symbol=?", (symbol, ), one=True) last_unix_time = row[1] if row else 0 for index, row in data_frame.iterrows(): row_unix_time = datetime.strptime(str(index), "%Y-%m-%d %H:%M:%S").timestamp() data_list = [row_unix_time] + list(row) if row_unix_time > last_unix_time: self.changes.append([symbol] + data_list) new_rows += 1 # There are cases where we could be parsing 0 rows. In that case, we will be making no new # additions to the symbol's prices, so the entry in last_updated should not be modified. # If this is a new symbol, we'll need to use INSERT INTO. If this symbol already exists # in the table, we'll need to use UPDATE. if len(data_frame) > 0: cur_time = time.time() if last_unix_time == 0: self.query_db("INSERT INTO last_updated VALUES (?, ?)", (symbol, cur_time)) else: self.query_db( "UPDATE last_updated SET time = ? WHERE symbol = ?", (cur_time, symbol)) return new_rows def get_prices(self, symbols, period, verbose=False): """ For all provided symbols, fetches data from AlphaVantage (assumed Standard API), parses each symbol's historic prices, and appends to self.changes the rows for every symbol that have not yet been written to the database. """ TIMEOUT = 0 if len(symbols) == 1 else 13 if verbose: print("Symbol\tLast refreshed\tFetched rows\tNew rows") for stock_symbol in symbols: data_frame = None metadata = None try: if period == "intraday": data_frame, metadata = self.time_series.get_intraday( symbol=stock_symbol, interval="5min", outputsize="full") elif period == "daily": data_frame, metadata = self.time_series.get_daily_adjusted( symbol=stock_symbol, outputsize="full") else: raise Exception( "Invalid period. Provide either 'intraday' or 'daily'." ) except ValueError as e: print(stock_symbol, e) continue new_rows = self.parse_changes_from_df(stock_symbol, data_frame) if verbose: print("{}\t{}\t{}\t\t{}".format(stock_symbol, metadata["3. Last Refreshed"], len(data_frame), new_rows)) time.sleep(TIMEOUT) def query_db(self, query, args=(), one=False): """ Executes the given query with the provided arguments and returns the results (if any are required). If 'one' is set to True, returns only the first result (or an empty tuple). """ cur = self.connection.execute(query, args) query_list = cur.fetchall() cur.close() self.connection.commit() return (query_list[0] if query_list else ()) if one else query_list # TODO: find some other way to do this. We should make an analogue to executemany(). def commit_changes(self): """ Inserts all rows in self.changes into the database. """ # Preset number of columns. Bad practice? Probably. self.connection.executemany( "INSERT INTO prices VALUES (?,?,?,?,?,?,?,?,?,?)", self.changes) self.connection.commit()
def get_alphavantage_compact_data(symbol=None): if symbol is None: symbol = 'MSFT' ts = TimeSeries(output_format='pandas', indexing_type='date') return ts.get_daily_adjusted(symbol=symbol, outputsize='compact')
def grabData(key, input_ticker, delta): tS = TimeSeries(key=key, output_format='pandas', indexing_type='date') tI = TechIndicators(key=key, output_format='pandas') data, meta_data = tS.get_daily_adjusted( symbol=input_ticker, outputsize='full') #compact for last 100 or full for everything macd, macd_meta = tI.get_macd(symbol=input_ticker, interval='daily', series_type='close') rsi, rsi_meta = tI.get_rsi(symbol=input_ticker, interval='daily', time_period=14, series_type='close') willr, willr_meta = tI.get_willr(symbol=input_ticker, interval='daily', time_period=14) adx, adx_meta = tI.get_adx(symbol=input_ticker, interval='daily', time_period=14) mom, mom_meta = tI.get_mom(symbol=input_ticker, interval='daily', time_period=10, series_type='close') all_vals = [data, macd, rsi, willr, adx, mom] final_df = pd.concat( all_vals, axis=1, sort=True ) # Sort arg may need to be False, leaving it blank raises Pandas error final_df = final_df.dropna() df = final_df.iloc[::-1] df = df.reset_index() df = df.drop(['6. volume', '7. dividend amount'], axis=1) # ************************************************************************* labels = [] priceDiffernces = [] for index, row in df.iterrows(): if 0 <= index < delta: pass else: initPrice = row[5] deltaPrice = df.iloc[index - delta][5] priceDiffernces.append(round((deltaPrice - initPrice), 2)) if deltaPrice > initPrice: labels.append(1) else: labels.append(0) df = df.drop(list(range(delta))) labelsPD = pd.Series(labels) priceDiffsPD = pd.Series(priceDiffernces) df['Labels'] = labelsPD.values df['Price Diffs'] = priceDiffsPD.values df.to_csv(input_ticker + '.csv')
def fetch_graph_results(strategy_name, investment_per_strategy, stock_symbol_array): stock_details = [] five_days_history = [] investment_per_company = investment_per_strategy / 3 for stock_symbol in stock_symbol_array: ts = TimeSeries(key='L7LPZFOTDXED8KS0') data, meta_data = ts.get_daily_adjusted(stock_symbol) if meta_data: count = 0 for each_entry in data: if count < 5: stock_details.append( [strategy_name, stock_symbol, each_entry, data[each_entry]['5. adjusted close']]) five_days_history.append(each_entry) count = count + 1 else: break first_day = [] first_day_history = [] second_day_history = [] third_day_history = [] fourth_day_history = [] fifth_day_history = [] first_day_investment = 0 second_day_investment = 0 third_day_investment = 0 forth_day_investment = 0 fifth_day_investment = 0 graph_results = [] graph_results_detailed = [] for entry in stock_details: if entry[2] == sorted(set(five_days_history))[0]: first_day.append([entry[1], entry[3]]) no_of_stocks_per_company = math.floor(investment_per_company / float(entry[3])) first_day_history.append([entry[1], round(float(entry[3]), 2), no_of_stocks_per_company]) first_day_investment += no_of_stocks_per_company * float(entry[3]) graph_results.append([sorted(set(five_days_history))[0], round(first_day_investment, 2)]) for entry in stock_details: if entry[2] == sorted(set(five_days_history))[1]: for company in first_day_history: if company[0] == entry[1]: second_day_history.append([entry[1], round(float(entry[3]), 2), company[2]]) second_day_investment += (float(entry[3]) * company[2]) elif entry[2] == sorted(set(five_days_history))[2]: for company in first_day_history: if company[0] == entry[1]: third_day_history.append([entry[1], round(float(entry[3]), 2), company[2]]) third_day_investment += (float(entry[3]) * company[2]) elif entry[2] == sorted(set(five_days_history))[3]: for company in first_day_history: if company[0] == entry[1]: fourth_day_history.append([entry[1], round(float(entry[3]), 2), company[2]]) forth_day_investment += (float(entry[3]) * company[2]) elif entry[2] == sorted(set(five_days_history))[4]: for company in first_day_history: if company[0] == entry[1]: fifth_day_history.append([entry[1], round(float(entry[3]), 2), company[2]]) fifth_day_investment += (float(entry[3]) * company[2]) graph_results.append([sorted(set(five_days_history))[1], round(second_day_investment, 2)]) graph_results.append([sorted(set(five_days_history))[2], round(third_day_investment, 2)]) graph_results.append([sorted(set(five_days_history))[3], round(forth_day_investment, 2)]) graph_results.append([sorted(set(five_days_history))[4], round(fifth_day_investment, 2)]) graph_results_detailed.append([sorted(set(five_days_history))[0], first_day_history]) graph_results_detailed.append([sorted(set(five_days_history))[1], second_day_history]) graph_results_detailed.append([sorted(set(five_days_history))[2], third_day_history]) graph_results_detailed.append([sorted(set(five_days_history))[3], fourth_day_history]) graph_results_detailed.append([sorted(set(five_days_history))[4], fifth_day_history]) return graph_results, graph_results_detailed
import quandl # financial data source import pandas as pd # for dataframe setup and csv loading from datetime import datetime # timse series: date convention import matplotlib.pyplot as plt # module for plotting import os # for input/output of files/directories import plotly.offline as pyo import plotly.graph_objs as go from alpha_vantage.timeseries import TimeSeries TICKER = 'EOD/AMZN' # use either EOD or XNAS(datasets) / then ticker TICKER2 = TICKER[-4:] # change according to number of ticker characters symbol = TICKER2 os.chdir(r'D:\Users\jong\PyProjects\Stocks\US Stocks') key = open('alphavantage.txt', 'r').read() ts = TimeSeries(key=key, output_format='pandas') data = data, meta_data = ts.get_daily_adjusted(symbol=symbol, outputsize='full') data = data.reset_index() data['date'] = pd.to_datetime(data['date']) data.set_index('date', inplace=True) print(data.tail()) x = data.index dfA = data['4. close'] y1 = dfA Product_A = [ go.Scatter( x=x, y=y1, mode='lines', # 'markers+lines' line={
def dataimport(): ###Main program of this python file that imports data from alphavantage, ###and exports a csv file with historical data of the listed stocks #Import the list of DJIA companies during the 17year span #This creates a matrix of dates on top, and then 30 companies in DJIA djiacompanies = pd.read_csv( '/Users/takuyawakayama/Desktop/Columbia/APMA4903 Seminar/djia-components.csv' ) #Create list of dates that there was an index change #type=DatetimeIndex, list of dates of form datetime64[ns] switchdates = pd.to_datetime(list(djiacompanies)) #Lists all companies that we might ever use. type = LIST allcompanies = pd.Series(djiacompanies.values.ravel()).unique().tolist() #API key for Alphavantage apikey = 'AU6S38KFU04HJB8S' outputsize = 'full' #Initialize dataframe using AAPL as sample company ts = TimeSeries(key=apikey, output_format='pandas') totaldatadf, meta_data = ts.get_daily_adjusted(symbol='AAPL', outputsize=outputsize) columns = [ 'low', 'open', 'high', 'close', 'volume', 'split coefficient', 'dividend amount' ] totaldatadf.drop(columns, inplace=True, axis=1) totaldatadf = totaldatadf.rename(columns={'adjusted close': 'nan'}) #Create dataframe of historical daily prices for each company ever in DJIA for company in allcompanies: #Sometimes gives Error 503, so force program to complete connected = False while not connected: try: companydatadf, meta_data = ts.get_daily_adjusted( symbol=company, outputsize=outputsize) columns = [ 'low', 'open', 'high', 'close', 'volume', 'split coefficient', 'dividend amount' ] companydatadf.drop(columns, inplace=True, axis=1) companydatadf = companydatadf.rename( columns={'adjusted close': company}) totaldatadf = pd.concat([totaldatadf, companydatadf], axis=1) connected = True except: time.sleep(10) pass #Delete sample column totaldatadf.drop('nan', axis=1, inplace=True) #Reorder totaldatadf = totaldatadf.iloc[::-1] #Export to CSV totaldatadf.to_csv("totaldata.csv") return
symbols = [ 'CHKP', 'CRWD', 'CSCO', 'CYBR', 'FEYE', 'FTNT', 'MIME', 'NET', 'NLOK', 'OKTA', 'PANW', 'PFPT', 'QLYS', 'RPD', 'SAIL', 'SPLK', 'SUMO', 'TENB', 'ZS' ] for symbol in symbols: data = { "function": "OVERVIEW", "symbol": symbol, "outputsize": "compact", "datatype": "json", "apikey": key, } Stonk_Today = ts.get_quote_endpoint(symbol) Stonk_Monthly = ts.get_monthly_adjusted(symbol) Stonk_Daily = ts.get_daily_adjusted(symbol) response = requests.get(API_URL, data) Company_Overview = response.json() market_cap_billions = round( int(Company_Overview['MarketCapitalization']) / 1000000000, 1) ev_to_revenue = round(float(Company_Overview['EVToRevenue']), 1) stonk_price_today = float(Stonk_Today[0]['05. price']) try: stonk_price_jan_1 = float(Stonk_Monthly[0]['1. open']['2020-01-31'][0]) ytd_stonk_change_percent = '{:.1%}'.format(stonk_price_today / stonk_price_jan_1 - 1) except:
def display(): if request.method == 'GET': return f"Try going to '/form' to Submit the form" if request.method == 'POST': form_data = request.form # initializing alpha_vantage API alpha_vantage_api_key = "6ZXYDMYP08NQJ2XV" month_to_digit = { 'Januray': 1, 'Februray': 2, 'March': 3, 'April': 4, 'May': 5, 'June': 6, 'July': 7, 'August': 8, 'September': 9, 'October': 10, 'November': 11, 'December': 12 } which_month = form_data.get('months') input_month = month_to_digit.get(which_month) ticker_name = form_data.get('stock') #Generate Alpha Vantage time series object ts = TimeSeries(key=alpha_vantage_api_key, output_format='pandas') data, meta_data = ts.get_daily_adjusted(ticker_name, outputsize="compact") data['date_time'] = data.index cols = [ '1. open', '2. high', '3. low', '4. close', '5. adjusted close', 'date_time' ] df = data[cols] df.columns = [ 'open', 'high', 'low', 'close', 'adjusted close', 'date_time' ] dfc = df.copy() dfc.loc[:, 'month'] = df.apply(lambda x: x['date_time'].month, axis=1) dfc.loc[:, 'day'] = df.apply(lambda x: x['date_time'].day, axis=1) df_final = dfc[dfc['month'] == input_month] df_final = df_final.sort_values(by='date_time', ascending=True) y = df_final['close'].values x = df_final['day'].values title = 'Close price of ' + ticker_name + ' in month of ' + which_month fig = figure(plot_width=600, plot_height=600) fig.line(x, y, legend=title) # grab the static resources js_resources = INLINE.render_js() css_resources = INLINE.render_css() # render template script, div = components(fig) return render_template('display.html', form_data=form_data, plot_script=script, plot_div=div, js_resources=js_resources, css_resources=css_resources, author=author)
from alpha_vantage.techindicators import TechIndicators from urllib2 import HTTPError import time import numpy as np from alpha_vantage.timeseries import TimeSeries text_file = open("weekly.sel", "r") symbols = text_file.read().split() bullish_daily = [] cross_SMA = [] green3 = [] ts = TimeSeries(key='MKAV2AXSQSPRE2R0', output_format='pandas') for s in symbols: try: data, meta_data = ts.get_daily_adjusted(symbol=s) close_price = data["close"] open_price = data["open"] high5 = max(data["high"][-5:-1]) low5 = min(data["low"][-5:-1]) sma10 = np.mean(close_price[-10:-1]) sma15 = np.mean(close_price[-15:-1]) sma20 = np.mean(close_price[-20:-1]) if (sma10 > sma15 and sma15 > sma20): bullish_daily.append(s) if (high5 >= sma10 and low5 <= sma20 and high5 >= 1.05 * low5): cross_SMA.append(s) count = 0 for i in range(-4, -1): if open_price[i] < close_price[i]: count = count + 1
#testing range of dates start_date = '2017-07-23' end_date = '2018-07-23' #Portfolio size portfolio_size = 10 # In[340]: #grab closing data from s&p as a whole from alpha_vantage.timeseries import TimeSeries ts = TimeSeries(key = 'BEII34ZY6UI335CP', output_format = 'pandas') indicies_av, metadata = ts.get_daily_adjusted('^GSPC', outputsize = 'full') s_and_p_data = indicies_av.loc[five_yrs_ago:]["4. close"] # In[147]: import numpy as np #pandas 0.22.0 required at the moment for Stocker: use pip install pandas=0.22.0 import pkg_resources pkg_resources.require("pandas==0.22.0") import pandas as pd from pandas_datareader import data as wb from datetime import datetime from dateutil.relativedelta import relativedelta from stocker import Stocker
month = string[5:7] day = string[8:] dt = date(int(year), int(month), int(day)) return dt ticker = 'SPX' duration = '' begin_time = '' end_time = '' ts = TimeSeries(key='G9RVRT562GWL8YZB', output_format='pandas') data, meta_data = ts.get_daily_adjusted(symbol=ticker, outputsize='compact') def return_dates(): print("First Date", data.index.values[0]) print("Last Date", data.index.values[-1]) a = convert_pd_datetime(data.index.values[0]) b = convert_pd_datetime(data.index.values[-1]) print("Period in days", float((b - a).days)) print("Period in years", float((b - a).days) / 365.25) return data.index.values[0], data.index.values[-1], float( (b - a).days), float((b - a).days) / 365.25
def load(l_args, s_ticker, s_start, s_interval, df_stock): parser = argparse.ArgumentParser( add_help=False, prog="load", description=""" Load a stock in order to perform analysis.""", ) parser.add_argument( "-t", "--ticker", action="store", dest="s_ticker", required=True, help="Stock ticker", ) parser.add_argument( "-s", "--start", type=valid_date, default="2015-01-01", dest="s_start_date", help="The starting date (format YYYY-MM-DD) of the stock", ) parser.add_argument( "-i", "--interval", action="store", dest="n_interval", type=int, default=1440, choices=[1, 5, 15, 30, 60], help="Intraday stock minutes", ) parser.add_argument( "--source", action="store", dest="source", type=check_sources, default="yf", help="Source of historical data. Intraday: Only 'av' available." "Daily: 'yf' and 'av' available.", ) try: # For the case where a user uses: 'load BB' if l_args: if "-" not in l_args[0]: l_args.insert(0, "-t") ns_parser = parse_known_args_and_warn(parser, l_args) if not ns_parser: return [s_ticker, s_start, s_interval, df_stock] except SystemExit: print("") return [s_ticker, s_start, s_interval, df_stock] # Update values: s_ticker = ns_parser.s_ticker.upper() s_start = ns_parser.s_start_date s_interval = str(ns_parser.n_interval) + "min" try: # Daily if s_interval == "1440min": if ns_parser.source == "av": ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") # pylint: disable=unbalanced-tuple-unpacking df_stock, _ = ts.get_daily_adjusted(symbol=ns_parser.s_ticker, outputsize="full") # pylint: disable=no-member df_stock.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected df_stock = df_stock[ns_parser.s_start_date:] elif ns_parser.source == "yf": df_stock = yf.download(ns_parser.s_ticker, start=ns_parser.s_start_date, progress=False) # Check that a stock was successfully retrieved if df_stock.empty: print("") return [s_ticker, s_start, s_interval, df_stock] df_stock = df_stock.rename( columns={ "Open": "1. open", "High": "2. high", "Low": "3. low", "Close": "4. close", "Adj Close": "5. adjusted close", "Volume": "6. volume", }) df_stock.index.name = "date" if df_stock.index[0] > s_start: s_start = df_stock.index[0] # Intraday else: if ns_parser.source == "av": ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") # pylint: disable=unbalanced-tuple-unpacking df_stock, _ = ts.get_intraday(symbol=ns_parser.s_ticker, outputsize="full", interval=s_interval) # pylint: disable=no-member df_stock.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected df_stock = df_stock[ns_parser.s_start_date:] elif ns_parser.source == "yf": print( "Unfortunately, yahoo finance historical data doesn't contain intraday prices" ) return [s_ticker, s_start, s_interval, df_stock] except Exception as e: print(e) print("Either the ticker or the API_KEY are invalids. Try again!\n") return [s_ticker, s_start, s_interval, df_stock] s_intraday = (f"Intraday {s_interval}", "Daily")[s_interval == "1440min"] if s_start: print( f"Loading {s_intraday} {s_ticker} stock with starting period {s_start.strftime('%Y-%m-%d')} for analysis." ) else: print(f"Loading {s_intraday} {s_ticker} stock for analysis.") print("") return [s_ticker, s_start, s_interval, df_stock]
import os from flask import ( Flask, flash, render_template, redirect, request, session, url_for) from alpha_vantage.timeseries import TimeSeries from flask_pymongo import PyMongo from bson.objectid import ObjectId # instancing Flask app = Flask(__name__) # instancing Alpha Advantage API in order to retrieve quotes app_alpha = TimeSeries("Alpha_Advantage_key") # instancing access to MongoDB database app.config["MONGO_DBNAME"] = os.environ.get("MONGO_DBNAME") app.config["MONGO_URI"] = os.environ.get("MONGO_URI") app.secret_key = os.environ.get("secret_key") mongo = PyMongo(app) # Retrieve stock info from Alpha Advantage API stock_aapl = app_alpha.get_daily_adjusted("AAPL")
def view(l_args, s_ticker, s_start, s_interval, df_stock): parser = argparse.ArgumentParser( add_help=False, prog="view", description= "Visualize historical data of a stock. An alpha_vantage key is necessary.", ) if s_ticker: parser.add_argument( "-t", "--ticker", action="store", dest="s_ticker", default=s_ticker, help="Stock ticker", ) else: parser.add_argument( "-t", "--ticker", action="store", dest="s_ticker", required=True, help="Stock ticker", ) parser.add_argument( "-s", "--start", type=valid_date, dest="s_start_date", default=s_start, help="The starting date (format YYYY-MM-DD) of the stock", ) parser.add_argument( "-i", "--interval", action="store", dest="n_interval", type=int, default=0, choices=[1, 5, 15, 30, 60], help="Intraday stock minutes", ) parser.add_argument( "--type", action="store", dest="type", type=check_ohlc, default="a", # in case it's adjusted close help=("ohlc corresponds to types: open; high; low; close; " "while oc corresponds to types: open; close"), ) try: ns_parser = parse_known_args_and_warn(parser, l_args) if not ns_parser: return except SystemExit: print("") return # Update values: s_ticker = ns_parser.s_ticker # A new interval intraday period was given if ns_parser.n_interval != 0: s_interval = str(ns_parser.n_interval) + "min" type_candles = lett_to_num(ns_parser.type) try: ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") # Daily if s_interval == "1440min": # pylint: disable=unbalanced-tuple-unpacking df_stock, _ = ts.get_daily_adjusted(symbol=s_ticker, outputsize="full") # Intraday else: # pylint: disable=unbalanced-tuple-unpacking df_stock, _ = ts.get_intraday(symbol=s_ticker, outputsize="full", interval=s_interval) except Exception as e: print(e) print("Either the ticker or the API_KEY are invalids. Try again!") return df_stock.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected df_stock = df_stock[ns_parser.s_start_date:] # Daily if s_interval == "1440min": # The default doesn't exist for intradaily data ln_col_idx = [int(x) - 1 for x in list(type_candles)] # Check that the types given are not bigger than 4, as there are only 5 types (0-4) # pylint: disable=len-as-condition if len([i for i in ln_col_idx if i > 4]) > 0: print( "An index bigger than 4 was given, which is wrong. Try again") return # Append last column of df to be filtered which corresponds to: 6. Volume ln_col_idx.append(5) # Intraday else: # The default doesn't exist for intradaily data if ns_parser.type == "a": ln_col_idx = [3] else: ln_col_idx = [int(x) - 1 for x in list(type_candles)] # Check that the types given are not bigger than 3, as there are only 4 types (0-3) # pylint: disable=len-as-condition if len([i for i in ln_col_idx if i > 3]) > 0: print( "An index bigger than 3 was given, which is wrong. Try again") return # Append last column of df to be filtered which corresponds to: 5. Volume ln_col_idx.append(4) # Plot view of the stock plot_view_stock(df_stock.iloc[:, ln_col_idx], ns_parser.s_ticker)
def negmod(x): if type(x)==type(str(x)): if 'M' and "-" in x: if len(x) > 1: return str(float(x.replace('M', '')) * 1000000) gonogo="pass" AVkey="E82V6HPLXDMUN5TM" tickerbox=["OPK", "DGX", "NVTA", "LH"] for i in tickerbox: tickername=i ts=TimeSeries(key=AVkey, output_format='pandas') tickerdic={} for ticker in tickername: data, meta_data=ts.get_daily_adjusted(ticker) tickerdic[ticker]=data percentchangefilter=1 df=data style.use("ggplot") start=dt.datetime.today()-dt.timedelta(days=10) end=dt.datetime.today() #df=web.DataReader(tickername, "google", start, end) df["HL_PCT"]=(df["2. high"]-df["3. low"])/df["3. low"]*100.0 df["PCT_change"]=(df["5. adjusted close"]-df["1. open"])/df["1. open"]*100.0 #print(df.head()) ###could also have a nltk filter up here as well #filter for generate reports #could make a class and have different def modules to call
class AlphaVantageTicker(Ticker): '''Ticker implementation for the Alpha-Vantage API. Example: ``` ticker = AlphaVantageTicker('<KEY>') data = ticker.historic('MSFT', start=None) ``` Args: key: `str` key for the alpha vantage API (if None try to load through `utils.read_keys()`) outputsize: `str` of either `full` or `compact` that defines the return values from the API. ''' def __init__(self, key=None, outputsize='full'): # check if key should be updated if key is None: key = utils.read_keys()['alphavantage'] # retrieve the data self.__key = key self.ts = TimeSeries(key=self.__key, output_format='pandas') self._out = outputsize def price(self, symbol): '''Retrieves the current price of the given stock. Args: symbol: `str` of the symbol name Returns: `dict` that contains open, close, volume, high, low, timestamp ''' # retrieve the data data, meta_data = self.ts.get_intraday(symbol, interval='1min', outputsize='compact') price = data[-1:] # adjust time tz = utils.parse_time(price.index[0], "%Y-%m-%d %H:%M:%S", meta_data["6. Time Zone"]) # TODO: adjust to current timezone? # generate the output return {'timestamp': tz, 'open': price['1. open'][0], 'close': price['4. close'][0], 'high': price['2. high'][0], 'low': price['3. low'][0], 'volume': price['5. volume'][0]} def __search_key(self, dic, str): '''Helper function to find an entry in dicts.''' p = re.compile('.*{}.*'.format(str), re.IGNORECASE) for key in dic: m = p.match(key) if m is not None: return key def historic(self, symbol, start, end=None, resolution="daily"): '''Retrieves the historic prices from Args: symbol: `str` of the symbol name start: `datetime` or `long` of the starting point (`None` = from earliest) end: `datetime` or `long` of the ending point (`None` = up to current) resolution: `TickerResolution` or `str` on the resolution of the data. (strings can be `weekly`, `monthly`, `daily`, '<X>min', whereby X is replaced by a number) Returns: `pd.dataframe` with a `pd.DatetimeIndex` and columns `open`, `close`, `low`, `high`, `volume`. ''' # safty: covnert input data start = utils.safe_datetime(start) end = utils.safe_datetime(end) # safty: check input data if (start is not None and start.tzinfo is None) or (end is not None and end.tzinfo is None): print("WARNING: `start` and/or `end` timestamps appear not to have a timezone!") # handle resolution if isinstance(resolution, str): resolution = TickerResolution.from_string(resolution) time_format = '%Y-%m-%d' # check for correct granularity if resolution.granularity == TickerGranularity.DAILY: if resolution.adjusted: data, md = self.ts.get_daily_adjusted(symbol, outputsize=self._out) else: data, md = self.ts.get_daily(symbol, outputsize=self._out) elif resolution.granularity == TickerGranularity.WEEKLY: if resolution.adjusted: data, md = self.ts.get_weekly_adjusted(symbol) else: data, md = self.ts.get_weekly(symbol) elif resolution.granularity == TickerGranularity.MONTHLY: if resolution.adjusted: data, md = self.ts.get_monthly_adjusted(symbol) else: data, md = self.ts.get_monthly(symbol) else: # retrieve number closed to predef minute intervals mins = utils.math.take_smallest_closest(resolution.min_interval, [1,5,15,30,60]) time_format = '%Y-%m-%d %H:%M:%S' # retrieve the data data, md = self.ts.get_intraday(symbol, interval="{}min".format(mins), outputsize=self._out) # TODO: filter the data in pandas (according to actual resolution data) # format the data tz = pytz.timezone(md[self.__search_key(md, "Time Zone")]) data.rename(columns={'1. open':'open', '2. high':'high', '3. low':'low', '4. close': 'close', '5. volume': 'volume'}, inplace=True) data.index = data.index.map( lambda x:tz.localize( x ) ) # filter on the given time series if end is not None: data = data.loc[start:end] else: data = data.loc[start:] return data
class AlphaVantageData(DataSource): SOURCE = "ALPHAVANTAGE" MIN_TIMESTEP = "minute" TIMESTEP_MAPPING = [ { "timestep": "minute", "represntations": ["1min"] }, { "timestep": "day", "represntations": ["1D"] }, ] def __init__(self, config, max_workers=24, **kwargs): # Alpaca authorize 200 requests per minute and per API key # Setting the max_workers for multithreading with a maximum # of 200 self.name = "alphavantage" self.max_workers = min(max_workers, 24) # Stores self._data_store_minutes = {} self._data_store_days = {} # Connection to alphavantage REST API self.config = config self.api_key = config.API_KEY self.api = TimeSeries(key=self.api_key, output_format="csv") def _get_store(self, timestep): if timestep == "minute": return self._data_store_minutes return self._data_store_days def _csv_to_list(self, csv_reader): columns = next(csv_reader) data = [] for row in csv_reader: data.append(dict(zip(columns, row))) return data def _request_minutes_data(self, symbol, slice): csv_reader, metadata = self.api.get_intraday_extended(symbol, interval="1min", slice=slice) data = self._csv_to_list(csv_reader) return data def _request_daily_data(self, symbol): csv_reader, metadata = self.api.get_daily_adjusted(symbol, outputsize="full") data = self._csv_to_list(csv_reader) return data def _request_data(self, symbol, timestep): if timestep == "minute": slices = [ f"year{i}month{j}" for i in range(1, 3) for j in range(1, 13) ] with ThreadPoolExecutor( max_workers=self.max_workers, thread_name_prefix=f"{self.name}_requesting_data", ) as executor: tasks = [] for slice in slices: tasks.append( executor.submit(self._request_minutes_data, symbol, slice)) data = [] for task in as_completed(tasks): data.extend(task.result()) else: data = self._request_daily_data(symbol) return data def _append_data(self, symbol, data, timestep): store = self._get_store(timestep) df = pd.DataFrame(data) if "time" in df.columns: index_column = "time" else: index_column = "timestamp" df.set_index(index_column, inplace=True) df.sort_index(inplace=True) df.index = df.index.map( lambda d: datetime.strptime(d, "%Y-%m-%d")).tz_localize( self.DEFAULT_TIMEZONE) store[symbol] = df return df def _pull_source_symbol_bars(self, symbol, length, timestep=MIN_TIMESTEP, timeshift=None): self._parse_source_timestep(timestep, reverse=True) store = self._get_store(timestep) if symbol in store: data = store[symbol] else: data = self._request_data(symbol, timestep) if not data: raise NoDataFound(self.SOURCE, symbol) data = self._append_data(symbol, data, timestep) if timeshift: end = datetime.now() - timeshift end = self.to_default_timezone(end) data = data[data.index <= end] result = data.tail(length) return result def _pull_source_bars(self, symbols, length, timestep=MIN_TIMESTEP, timeshift=None): """pull broker bars for a list symbols""" result = {} self._parse_source_timestep(timestep, reverse=True) for symbol in symbols: result[symbol] = self._pull_source_symbol_bars(symbol, length, timestep=timestep, timeshift=timeshift) return result def _parse_source_symbol_bars(self, response, symbol): df = response.copy() if "adjusted_close" in df.columns: del df["adjusted_close"] if "dividend_amount" in df.columns: df.rename(columns={"dividend_amount": "dividend"}, inplace=True) else: df["dividend"] = 0 if "split_coefficient" in df.columns: df.rename(columns={"split_coefficient": "stock_splits"}, inplace=True) else: df["stock_splits"] = 0 df = df.astype({ "open": "float64", "high": "float64", "low": "float64", "close": "float64", "volume": "int64", "dividend": "float64", "stock_splits": "float64", }) df["price_change"] = df["close"].pct_change() df["dividend_yield"] = df["dividend"] / df["close"] df["return"] = df["dividend_yield"] + df["price_change"] bars = Bars(df, self.SOURCE, symbol, raw=response) return bars
class AlphaVantageHistoricalMarketData(HistoricalMarketData): period_dict = \ { # '1min', '5min', '15min', '30min', '60min' Period.day: 'day', Period.minute: 'min', Period.hour: '60min' } columns_intra_historical_dict = \ { Bar.close: '4. close', Bar.open: '1. open', Bar.high: '2. high', Bar.low: '3. low', Bar.time: 'index', Bar.volume: '5. volume' } columns_eod_historical_dict = \ { Bar.close: '5. adjusted close', Bar.open: '1. open', Bar.high: '2. high', Bar.low: '3. low', Bar.time: 'index', Bar.volume: '6. volume' } timeseries = None def __init__(self, user_settings): HistoricalMarketData.__init__(self, user_settings) self.timeseries = TimeSeries(key=user_settings.alphavantage_token, retries=3) pass def formatTime(self, timeColumn): import pandas as pd # The price comes from the daily info - # so it would be the price at the end of the day GMT based on the requested TS # http://pvlib-python.readthedocs.io/en/latest/timetimezones.html originTZ = 'Etc/GMT' datetimeSeries = pd.to_datetime(timeColumn) return pd.DatetimeIndex(pd.to_datetime(datetimeSeries, unit='ms')).tz_localize(originTZ).tz_convert( timezone_setting) def formatHistorical(self, input, period): import pandas as pd input_df = pd.DataFrame.from_dict(input).T output = pd.DataFrame(0, columns=Bar.columns, index=range(len(input_df))) input_df.reset_index(inplace=True) columnDict = self.columns_intra_historical_dict if period == Period.day: columnDict = self.columns_eod_historical_dict for column in output.columns: if column == Bar.time: timeProcessed = self.formatTime(input_df[columnDict[column]]) output[column] = timeProcessed else: output[column] = input_df[columnDict[column]].astype(float) output.set_index(Bar.index, inplace=True) return output # day unlimited # minute limited to 7 days! def download(self, instrument, period, number_of_periods, fromDate, toDate=None): import datetime logger.debug("Downloading %s" % instrument.symbol) try: if period != Period.day: # '1min', '5min', '15min', '30min', '60min' if number_of_periods in [1, 5, 15, 30, 60]: periodAlpha = '%i%s' % (number_of_periods, self.period_dict[period]) data_downloaded, meta_data = self.timeseries.get_intraday(instrument.symbol, interval=periodAlpha) else: logger.error( "AlphaVantage can only download intradaily! '1min', '5min', '15min', '30min', '60min' not %s" % period) return None else: # dateFormat = "%Y-%m-%d" if toDate is None: toDate = datetime.datetime.today() # download dataframe try: data_downloaded, meta_data = self.timeseries.get_daily_adjusted(instrument.symbol) # data_downloaded = pdr.get_data_yahoo(instrument.symbol, start=fromDate.strftime(dateFormat), end=toDate.strftime(dateFormat)) except Exception as e: logger.error("Cand download from alphavantage %s => return None %s" % (instrument.symbol, e)) return None except Exception as e: logger.error('Error downloading from alphavantage %s %s return None :%s' % (instrument.symbol, period, e)) return None outputComplete = self.formatHistorical(data_downloaded, period=period) outputComplete = self.setTimeCorrect(outputComplete, period=period, instrument=instrument) return outputComplete
def main(): """ Gamestonk Terminal is an awesome stock market terminal that has been developed for fun, while I saw my GME shares tanking. But hey, I like the stock. """ # Enable VT100 Escape Sequence for WINDOWS 10 Ver. 1607 if sys.platform == "win32": os.system("") s_ticker = "" s_start = "" df_stock = pd.DataFrame() s_interval = "1440min" # Set stock by default to speed up testing # s_ticker = "BB" # ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') # df_stock, d_stock_metadata = ts.get_daily_adjusted(symbol=s_ticker, outputsize='full') # df_stock.sort_index(ascending=True, inplace=True) # s_start = datetime.strptime("2020-06-04", "%Y-%m-%d") # df_stock = df_stock[s_start:] # Add list of arguments that the main parser accepts menu_parser = argparse.ArgumentParser(add_help=False, prog="gamestonk_terminal") choices = [ "help", "quit", "q", "clear", "load", "candle", "view", "export", "disc", "mill", "ba", "res", "fa", "ta", "dd", "pred", "ca", "op", "fred", "pa", ] menu_parser.add_argument("opt", choices=choices) completer = NestedCompleter.from_nested_dict({c: None for c in choices}) # Print first welcome message and help print("\nWelcome to Gamestonk Terminal 🚀\n") should_print_help = True parsed_stdin = False if gtff.ENABLE_THOUGHTS_DAY: print("-------------------") try: thought.get_thought_of_the_day() except Exception as e: print(e) print("") # Loop forever and ever while True: main_cmd = False if should_print_help: print_help(s_ticker, s_start, s_interval, b_is_stock_market_open()) should_print_help = False # Get input command from stdin or user if not parsed_stdin and len(sys.argv) > 1: as_input = " ".join(sys.argv[1:]) parsed_stdin = True print(f"{get_flair()}> {as_input}") elif session and gtff.USE_PROMPT_TOOLKIT: as_input = session.prompt(f"{get_flair()}> ", completer=completer) else: as_input = input(f"{get_flair()}> ") # Is command empty if not as_input: print("") continue # Parse main command of the list of possible commands try: (ns_known_args, l_args) = menu_parser.parse_known_args(as_input.split()) except SystemExit: print("The command selected doesn't exist\n") continue b_quit = False if ns_known_args.opt == "help": should_print_help = True elif (ns_known_args.opt == "quit") or (ns_known_args.opt == "q"): break elif ns_known_args.opt == "clear": s_ticker, s_start, s_interval, df_stock = clear( l_args, s_ticker, s_start, s_interval, df_stock) main_cmd = True elif ns_known_args.opt == "load": s_ticker, s_start, s_interval, df_stock = load( l_args, s_ticker, s_start, s_interval, df_stock) main_cmd = True elif ns_known_args.opt == "candle": if s_ticker: candle( s_ticker, (datetime.now() - timedelta(days=180)).strftime("%Y-%m-%d"), ) else: print( "No ticker selected. Use 'load ticker' to load the ticker you want to look at.", "\n", ) main_cmd = True elif ns_known_args.opt == "view": if s_ticker: view(l_args, s_ticker, s_start, s_interval, df_stock) else: print( "No ticker selected. Use 'load ticker' to load the ticker you want to look at." ) main_cmd = True elif ns_known_args.opt == "export": export(l_args, df_stock) main_cmd = True elif ns_known_args.opt == "disc": b_quit = dm.disc_menu() elif ns_known_args.opt == "mill": b_quit = mill.papermill_menu() elif ns_known_args.opt == "ba": b_quit = ba_controller.menu(s_ticker, s_start) elif ns_known_args.opt == "res": b_quit = rm.res_menu(s_ticker, s_start, s_interval) elif ns_known_args.opt == "ca": b_quit = ca_controller.menu(df_stock, s_ticker, s_start, s_interval) elif ns_known_args.opt == "fa": b_quit = fam.fa_menu(s_ticker, s_start, s_interval) elif ns_known_args.opt == "ta": b_quit = tam.ta_menu(df_stock, s_ticker, s_start, s_interval) elif ns_known_args.opt == "dd": b_quit = ddm.dd_menu(df_stock, s_ticker, s_start, s_interval) elif ns_known_args.opt == "op": b_quit = opm.opt_menu(s_ticker) elif ns_known_args.opt == "fred": b_quit = fm.fred_menu() elif ns_known_args.opt == "pa": b_quit = port_controller.menu() elif ns_known_args.opt == "pred": if not gtff.ENABLE_PREDICT: print("Predict is not enabled in feature_flags.py") print("Prediction menu is disabled") print("") continue try: # pylint: disable=import-outside-toplevel from gamestonk_terminal.prediction_techniques import pred_menu as pm except ModuleNotFoundError as e: print("One of the optional packages seems to be missing") print("Optional packages need to be installed") print(e) print("") continue except Exception as e: print(e) print("") continue if s_interval == "1440min": b_quit = pm.pred_menu(df_stock, s_ticker, s_start, s_interval) # If stock data is intradaily, we need to get data again as prediction # techniques work on daily adjusted data. By default we load data from # Alpha Vantage because the historical data loaded gives a larger # dataset than the one provided by quandl else: try: ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") # pylint: disable=unbalanced-tuple-unpacking df_stock_pred, _ = ts.get_daily_adjusted(symbol=s_ticker, outputsize="full") # pylint: disable=no-member df_stock_pred = df_stock_pred.sort_index(ascending=True) df_stock_pred = df_stock_pred[s_start:] b_quit = pm.pred_menu(df_stock_pred, s_ticker, s_start, s_interval="1440min") except Exception as e: print(e) print( "Either the ticker or the API_KEY are invalids. Try again!" ) return else: print("Shouldn't see this command!") continue if b_quit: break else: if not main_cmd: should_print_help = True print( "Hope you enjoyed the terminal. Remember that stonks only go up. Diamond hands.\n" )
class BackTestSMA: def __init__(self, argkey=None, argscript=None, argscripttree=None, arglistholdingcols=None, argstartdt=None, argenddt=None, argavgsmall=None, argavglarge=None, argIsTest=False): super().__init__() self.key = argkey self.script = argscript self.startdt = argstartdt self.enddt = argenddt self.avgsmall = argavgsmall self.avglarge = argavglarge self.bool_test = argIsTest if (self.bool_test == False): self.ts = TimeSeries(self.key, output_format='pandas') self.ti = TechIndicators(self.key, output_format='pandas') self.treeofscripts = argscripttree self.dfholdingvalues = DataFrame() """ method - getScriptDataFromTree builds a DataFrame for all the portfolio holding values extracted from Tree HOLDING Values are stored in following order: [0] = value of 'Purchase Price' [1] = value of 'Purchase Date' [2] = value of 'Purchase Qty' [3] = value of 'Commission Paid' [4] = value of 'Cost of Investment' of buying Purchase QTY of scripts on Purchase Date [5] = value of 'Current Value' of the QTY at today's closing price [6] = value of 'Status' this is either '↑' or '↓' or '↔' what is needed is the self transaction information stored in Tree under HOLDINFVAL Assumming there are multiple buy transactions for the current script, we need to plot valuation in steps. For example: on 2020-02-24 there was a buy transacation for 2 shares at cost of 1000 + X%commission we need to plot the graph with daily price starting from 2020-02-24 There was one more buy transaction for the same script for 2 shares on 2020-03-10. Then from this date we need to show cumulative performance graph of all shares. Whar we will do is we will build a DataFrame with all such rows for the specific script then merge this DataFrame with the DataFrame from Alpha """ def getScriptDataFromTree(self): #get HOLDINGVAL of current script from tree allchildrows = self.treeofscripts.get_children(self.script) row_val = list() scriptQty = 0 self.dfholdingvalues = DataFrame() for child in allchildrows: if (str(child).upper().find(self.treeofscripts.HOLDINGVAL) >= 0): row_val = self.treeofscripts.item(child, 'values') #scriptQty += int(row_val[2]) d = { 'PurchaseDate': [row_val[1]], 'PurchasePrice': [row_val[0]], 'PurchaseQTY': [row_val[2]], 'Commission': [row_val[3]], 'CostofInvestment': [row_val[4]], 'CurrentValue': [row_val[5]], 'Status': [row_val[6]] } #tempDF = DataFrame.from_dict(data=d, orient='index') tempDF = DataFrame(d) #tempDF = tempDF.transpose() self.dfholdingvalues = self.dfholdingvalues.append( tempDF, ignore_index=True) #self.dfholdingvalues.set_index('PurchaseDate') convert_type = {'PurchaseQTY': float} self.dfholdingvalues = self.dfholdingvalues.astype(convert_type) convert_type = {'Commission': float} self.dfholdingvalues = self.dfholdingvalues.astype(convert_type) self.dfholdingvalues.sort_values('PurchaseDate', axis=0, inplace=True, ignore_index=True) sumoflastrows = 0 imax = self.dfholdingvalues.shape[0] for i in range(imax): #self.dfholdingvalues['PurchaseQTY'][i]=(self.dfholdingvalues['PurchaseQTY'][i])+sumoflastrows #sumoflastrows=self.dfholdingvalues['PurchaseQTY'][i] self.dfholdingvalues.loc[i, 'PurchaseQTY'] = self.dfholdingvalues.loc[ i, 'PurchaseQTY'] + sumoflastrows sumoflastrows = self.dfholdingvalues.loc[i, 'PurchaseQTY'] """ setCurrentValInMarketDF In this method we will need to add three columns to the Alpha returned DF 1. Purchase QTY, which is cumulative of QTY as of date 2. Current Value 3. Commission Paid now we need to add values in these columns in the Alpha DF i = 0 start of self.dfholdingvalues imax = self.dfholdingvalues.shape()[0] //returns tuple (no of rows, no of cols) for each row in Alpha DF first check if i < imax if( alpha.date >= self.dfholdingvalues[i].purchasedate AND alpha.date < self.dfholdingvalues[i+1].purchasedate) calculate the Alpha.CurretnValue = self.dfholdingvalues[i].QTY * Alpha.ClosePrice set Alpha.QTY = self.dfholdingvalues[i].QTY set Alpha.Commision = self.dfholdingvalues[i].commission else if alpha.date < self.dfholdingvalues[i].purchasedate do nothing (we must have all rows sortd by Date in Alpha) else if alpha.date < self.dfholdingvalues[i+1].purchasedate i += 1 calculate the Alpha.CurretnValue = self.dfholdingvalues[i].QTY * Alpha.ClosePrice set Alpha.QTY = self.dfholdingvalues[i].QTY set Alpha.Commision = self.dfholdingvalues[i].commission else if i == imax calculate the Alpha.CurretnValue = self.dfholdingvalues[i].QTY * Alpha.ClosePrice set Alpha.QTY = self.dfholdingvalues[i].QTY set Alpha.Commision = self.dfholdingvalues[i].commission """ def setCurrentValInMarketDF(self): #find the shape of self.dfholdingvalues. shape returns tuple (no of rows, no of cols) imax = self.dfholdingvalues.shape[0] i = 0 # we will only use data from the date of first purchase #self.dfScript = self.dfScript.loc[(self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][0])] self.dfScript = self.dfScript.loc[( self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][imax - 1])] for i in range(imax - 1, imax): if (i < imax - 1): #we have still not last row self.dfScript.loc[ ((self.dfScript.index[:] >= self. dfholdingvalues['PurchaseDate'][i]) & (self.dfScript.index[:] < self. dfholdingvalues['PurchaseDate'][i + 1])), 'PurchaseDate'] = self.dfholdingvalues['PurchaseDate'][i] self.dfScript.loc[ ((self.dfScript.index[:] >= self. dfholdingvalues['PurchaseDate'][i]) & (self.dfScript.index[:] < self. dfholdingvalues['PurchaseDate'][i + 1])), 'PurchaseQTY'] = self.dfholdingvalues['PurchaseQTY'][i] self.dfScript.loc[ ((self.dfScript.index[:] >= self. dfholdingvalues['PurchaseDate'][i]) & (self.dfScript.index[:] < self. dfholdingvalues['PurchaseDate'][i + 1])), 'Commission'] = self.dfholdingvalues['Commission'][i] #self.dfScript.loc[((self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][i]) & # (self.dfScript.index[:] < self.dfholdingvalues['PurchaseDate'][i])), 'CurrentVal'] = self.dfScript.loc[((self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][i]) & (self.dfScript.index[:] < self.dfholdingvalues['PurchaseDate'][i+1])), 'PurchaseQTY'] * self.dfScript.loc[((self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][i]) & (self.dfScript.index[:] < self.dfholdingvalues['PurchaseDate'][i+1])), 'Close'] else: self.dfScript.loc[ (self.dfScript.index[:] >= self. dfholdingvalues['PurchaseDate'][i]), 'PurchaseDate'] = self.dfholdingvalues['PurchaseDate'][i] self.dfScript.loc[ (self.dfScript.index[:] >= self. dfholdingvalues['PurchaseDate'][i]), 'PurchaseQTY'] = self.dfholdingvalues['PurchaseQTY'][i] self.dfScript.loc[ (self.dfScript.index[:] >= self. dfholdingvalues['PurchaseDate'][i]), 'Commission'] = self.dfholdingvalues['Commission'][i] #self.dfScript.loc[(self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][i]), 'CurrentVal'] = self.dfScript.loc[(self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][i]), 'PurchaseQTY'] * self.dfScript.loc[(self.dfScript.index[:] >= self.dfholdingvalues['PurchaseDate'][i]), 'Close'] self.dfScript.loc[(self.dfScript.index[:] == self.dfholdingvalues['PurchaseDate'][i]), 'Status'] = self.dfholdingvalues['Status'][i] self.dfScript['CurrentVal'] = self.dfScript[ 'PurchaseQTY'] * self.dfScript['Close'] """ changeColNameTypeofDailyTS d """ def changeColNameTypeofDailyTS(self): #rename columns self.dfScript = self.dfScript.rename( columns={ '1. open': 'Open', '2. high': 'High', '3. low': 'Low', '4. close': 'Close', '5. volume': 'Volume' }) #Add new columns self.dfScript['PurchaseDate'] = "" self.dfScript['PurchaseQTY'] = 0.00 self.dfScript['CurrentVal'] = 0.00 self.dfScript['Commission'] = 0.00 self.dfScript['Status'] = "" self.dfScript['Short_Mean'] = 0.00 self.dfScript['Long_Mean'] = 0.00 self.dfScript['Order'] = 0 self.dfScript['Returns'] = 0.00 self.dfScript['CumReturns'] = 0.00 convert_type = {'Close': float} self.dfScript = self.dfScript.astype(convert_type) convert_type = {'PurchaseQTY': float} self.dfScript = self.dfScript.astype(convert_type) convert_type = {'Commission': float} self.dfScript = self.dfScript.astype(convert_type) convert_type = {'CurrentVal': float} self.dfScript = self.dfScript.astype(convert_type) convert_type = {'Short_Mean': float} self.dfScript = self.dfScript.astype(convert_type) convert_type = {'Long_Mean': float} self.dfScript = self.dfScript.astype(convert_type) convert_type = {'Returns': float} self.dfScript = self.dfScript.astype(convert_type) convert_type = {'CumReturns': float} self.dfScript = self.dfScript.astype(convert_type) def addPerformance(self): #find the moving average as per the num of days specified by user onadjusted close #self.dfScript['Short_Mean']=self.dfScript.rolling(self.avgsmall).mean()['Close'] self.dfScript.loc[self.dfScript.index[:], 'Short_Mean'] = self.dfScript.rolling( self.avgsmall).mean()['Close'] #self.dfScript['Long_Mean']=self.dfScript.rolling(self.avglarge).mean()['Close'] self.dfScript.loc[self.dfScript.index[:], 'Long_Mean'] = self.dfScript.rolling( self.avglarge).mean()['Close'] #If the short moving average is now above the long moving average, # then we are on a short-term upwards trend. At least that is the theory. # That means, that we will buy. If the averages cross the other way around, we sell. # Otherwise we do nothing. #This means that we make a new column which consists of a one if the short moving # average is above the long moving average, otherwise it contains a zero. # The shift in the last line is, because we compute on the closing prices. # That means that we will then buy/sell on the next day, so we shift the buying # signal one day. self.dfScript.loc[ self.dfScript['Short_Mean'] > self.dfScript['Long_Mean'], 'Order'] = 1 #self.dfScript['Order']=self.dfScript['Order'].shift(1) self.dfScript.loc[self.dfScript.index[:], 'Order'] = self.dfScript['Order'].shift(1) #now we calculare relative returns for each day #rt=(pt−(pt−1))/(pt−1)=(pt/(pt−1))−1 self.dfScript['Returns'] = (self.dfScript['Close'] / ((self.dfScript['Close']).shift(1))) - 1 self.dfScript.loc[self.dfScript.index[:], 'Returns'] = (self.dfScript['Close'] / ( (self.dfScript['Close']).shift(1))) - 1 #We have only returns when we trade. That means that we multiply the returns with # the buying signal. self.dfScript[ 'Returns'] = self.dfScript['Returns'] * self.dfScript['Order'] self.dfScript.loc[ self.dfScript.index[:], 'Returns'] = self.dfScript['Returns'] * self.dfScript['Order'] #Since we reinvest all returns, we need to take a cumulative product # over the last column. # it=((it−1)+(it−1)*rt)=(1+rt)*(it−1),i0=1 self.dfScript['CumReturns'] = (1 + self.dfScript.Returns).cumprod() print(self.dfScript) """ plotPerformanceGraphTS d """ def plotPerformanceGraphTS(self): f_temp = Figure(figsize=(60, 60), dpi=80, facecolor='w', edgecolor='k') #first 3 & 1 means we want to show 3 graphs in 1 column #last 1 indicates the sequence number of the current graph ax1 = plt.subplot(221) #first plot the self portfolio performance using CurrentVal columns in dfScript plt.plot(self.dfScript['CurrentVal'], label='Portfolio price') # now we will put markers where the user has bought the scripts and show cumulative qty #buys=self.dfScript.loc[(self.dfScript['Status'] != ''), ['PurchaseDate', 'PurchaseQTY', 'Status']] buys = self.dfScript.loc[(self.dfScript['Status'] != ''), :] plt.plot(buys.index, self.dfScript['CurrentVal'].loc[buys.index], marker="*", markersize=10, color='b', label='Buy transaction', linestyle='None') for i in range(len(buys.index)): plt.annotate('Total Qty=' + str(buys['PurchaseQTY'][i]) + " " + buys['Status'][i], (mdates.datestr2num( buys['PurchaseDate'][i]), buys['CurrentVal'][i]), xytext=(15, 15), textcoords='offset points', arrowprops=dict(arrowstyle='-|>')) plt.ylabel("Portfolio Value") plt.legend() #(loc='upper left') plt.grid() # now plot 2nd set of graph #ax2 = plt.subplot(312, sharex=ax1) ax2 = plt.subplot(222) plt.plot(self.dfScript['Close'], label='Daily Close Price') plt.plot(buys.index, self.dfScript['Close'].loc[buys.index], marker="*", markersize=10, color='b', label='Buy transaction', linestyle='None') for i in range(len(self.dfholdingvalues.index)): plt.annotate( 'Qty=' + str(self.dfholdingvalues['PurchaseQTY'][i]) + " @ " + self.dfholdingvalues['PurchasePrice'][i], (mdates.datestr2num(self.dfholdingvalues['PurchaseDate'][i]), float(self.dfholdingvalues['PurchasePrice'][i])), xytext=(15, 15), textcoords='offset points', arrowprops=dict(arrowstyle='-|>')) plt.plot(self.dfScript['Short_Mean'], label='Short Mean') plt.plot(self.dfScript['Long_Mean'], label='Long Mean') buys_suggested = self.dfScript.loc[self.dfScript['Order'] == 1, 'Order'] #plt.plot(buys.index, self.dfScript.columns['Adj Close'].loc[buys.index], marker=6, markersize=10, color='g', label='buy', linestyle='None') plt.plot(buys_suggested.index, self.dfScript['Close'].loc[buys_suggested.index], marker=6, markersize=10, color='b', label='Buy', linestyle='None') sells_suggested = self.dfScript.loc[self.dfScript['Order'] == 0, 'Order'] #plt.plot(sells.index, self.dfScript.column['Adj Close'].loc[sells.index], marker=7, markersize=10, color='r', label='sell', linestyle='None') plt.plot(sells_suggested.index, self.dfScript['Close'].loc[sells_suggested.index], marker=7, markersize=10, color='r', label='Sell', linestyle='None') plt.ylabel('Price') plt.legend() #(loc='upper left') plt.grid() # Now plot 3rd set of graph for cum returns #ax3 = plt.subplot(313, sharex=ax1) ax3 = plt.subplot(223) plt.plot(self.dfScript['CumReturns'], label='Cumulative Returns') plt.ylabel('Cumulative Returns') plt.legend() #(loc='upper left') plt.grid() # Now plot 3rd set of graph for cum returns #ax3 = plt.subplot(313, sharex=ax1) ax3 = plt.subplot(224) plt.plot(self.dfScript['Returns'], label='Daily Returns') plt.ylabel('Daily Returns') plt.legend() #(loc='upper left') plt.grid() plt.suptitle(self.script) plt.show() """ findScriptPerformance This method will execute Alpha """ def findScriptPerformance(self): self.getScriptDataFromTree() if (self.dfholdingvalues.shape[0] < 1): msgbx.showwarning( "Script Performance", "No script data found. Please add your purchased scripts before doing performance calculations" ) return try: if (self.bool_test): testobj = PrepareTestData() self.dfScript = testobj.loadDaily(self.script) else: self.dfScript, meta_data = self.ts.get_daily( symbol=self.script, outputsize='full') self.dfScript.sort_index(axis=0, inplace=True) except ValueError as error: msgbx.showerror("Alpha Vantage error", error) return self.changeColNameTypeofDailyTS() self.setCurrentValInMarketDF() self.addPerformance() self.plotPerformanceGraphTS() """ Method - getData(self): Not used get_daily_adjusted returns data and metadata in DF data format example: "Time Series (Daily)": { "2020-03-03": { "1. open": "173.8000", "2. high": "175.0000", "3. low": "162.2600", "4. close": "164.5100", "5. adjusted close": "164.5100", "6. volume": "71033645", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-03-02": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "172.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }} """ def getDataNotUsed(self): self.dfScript, meta_data = self.ts.get_daily_adjusted(self.script) records = { "2020-03-03": { "1. open": "173.8000", "2. high": "175.0000", "3. low": "162.2600", "4. close": "164.5100", "5. adjusted close": "164.5100", "6. volume": "71033645", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-03-02": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "172.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-03-01": { "1. open": "111.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "111.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-29": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "222.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-28": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "333.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-27": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "444.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-26": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "555.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-25": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "888.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-24": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "111.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-23": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "222.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-22": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "333.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-21": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "444.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-20": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "888.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-19": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "333.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-18": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "555.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-17": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "454.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-16": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "345.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-15": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "234.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-14": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "678.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-13": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "111.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-12": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "123.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-11": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "124.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-10": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "122.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-09": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "127.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-08": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "124.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-07": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "127.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-06": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "222.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-05": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "211.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-04": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "212.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-03": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "213.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-02": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "214.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" }, "2020-02-01": { "1. open": "165.3100", "2. high": "172.9200", "3. low": "162.3100", "4. close": "172.7900", "5. adjusted close": "243.7900", "6. volume": "71030810", "7. dividend amount": "0.0000", "8. split coefficient": "1.0000" } } #print(records) #self.dfScript = pd.DataFrame(records.values(), columns=['1. open', "2. high", "3. low", "4. close", "5. adjusted close", # "6. volumn", "7. dividend amount", "8. split coefficient"]) #self.dfScript.index = records.keys() #result = DataFrame() #select only the date period specified by user #self.dfScript.index = pd.datetime(self.dfScript) #self.dfScript = self.dfScript.loc[self.startdt:self.enddt, :] #Not sure if we want to filter the date by dates #self.dfScript = self.dfScript.loc[self.startdt:self.enddt, :] #print(self.dfScript) #We want only the adjusted close self.dfScript = self.dfScript[['5. adjusted close']] convert_type = {'5. adjusted close': float} self.dfScript = self.dfScript.astype(convert_type) self.dfScript = self.dfScript.rename( columns={'5. adjusted close': 'Adj Close'}) #find the moving average as per the num of days specified by user onadjusted close self.dfScript['short_mean'] = self.dfScript.rolling(int( self.avgsmall)).mean()['Adj Close'] self.dfScript['long_mean'] = self.dfScript.rolling(int( self.avglarge)).mean()['Adj Close'] #Index is already named as "date" #self.dfScript=self.dfScript.rename_axis('Trans_Date') #print(self.dfScript) #If the short moving average is now above the long moving average, # then we are on a short-term upwards trend. At least that is the theory. # That means, that we will buy. If the averages cross the other way around, we sell. # Otherwise we do nothing. #This means that we make a new column which consists of a one if the short moving # average is above the long moving average, otherwise it contains a zero. # The shift in the last line is, because we compute on the closing prices. # That means that we will then buy/sell on the next day, so we shift the buying # signal one day. self.dfScript['order'] = 0 #self.dfScript['order'][self.dfScript.short_mean > self.dfScript.long_mean] = 1 #buy signal self.dfScript.loc[ self.dfScript['short_mean'] > self.dfScript['long_mean'], 'order'] = 1 self.dfScript['order'] = self.dfScript['order'].shift(1) #now we calculare relative returns for each day #rt=(pt−(pt−1))/(pt−1)=(pt/(pt−1))−1 self.dfScript['returns'] = (self.dfScript['Adj Close'] / ( (self.dfScript['Adj Close']).shift(1))) - 1 print(self.dfScript) #We have only returns when we trade. That means that we multiply the returns with # the buying signal. self.dfScript[ 'returns'] = self.dfScript['returns'] * self.dfScript['order'] print(self.dfScript) #Since we reinvest all returns, we need to take a cumulative product # over the last column. # it=((it−1)+(it−1)*rt)=(1+rt)*(it−1),i0=1 self.dfScript['cumreturns'] = (1 + self.dfScript.returns).cumprod() print(self.dfScript) #self.dfScript.plot() #plt.show() """ plotgraphs - Not used s """ def plotgraphsNotUsed(self): f_temp = Figure(figsize=(15, 6), dpi=80, facecolor='w', edgecolor='k') #first plot the Adj Close graph ax1 = plt.subplot(311) #Adj Close price plt.plot(self.dfScript['Adj Close'], label='Adjusted close price') buys = self.dfScript.loc[self.dfScript['order'] == 1, 'order'] #plt.plot(buys.index, self.dfScript.columns['Adj Close'].loc[buys.index], marker=6, markersize=10, color='g', label='buy', linestyle='None') plt.plot(buys.index, self.dfScript['Adj Close'].loc[buys.index], marker=6, markersize=10, color='b', label='buy', linestyle='None') sells = self.dfScript.loc[self.dfScript['order'] == 0, 'order'] #plt.plot(sells.index, self.dfScript.column['Adj Close'].loc[sells.index], marker=7, markersize=10, color='r', label='sell', linestyle='None') plt.plot(sells.index, self.dfScript['Adj Close'].loc[sells.index], marker=7, markersize=10, color='r', label='sell', linestyle='None') plt.legend() #(loc='upper left') plt.grid() #Average - short & long ax2 = plt.subplot(312, sharex=ax1) plt.plot(self.dfScript['short_mean'], label='Short Mean') plt.plot(self.dfScript['long_mean'], label='Long Mean') plt.legend() #(loc='upper left') plt.grid() ax3 = plt.subplot(313, sharex=ax1) plt.plot(self.dfScript['cumreturns'], label='Cumulative Returns') plt.legend() #(loc='upper left') plt.grid() plt.suptitle(self.script) plt.show()
import os import stocktrends import pandas as pd from alpha_vantage.timeseries import TimeSeries key = os.environ.get('ALPHAVANTAGE_KEY') print(key) ts = TimeSeries(key=key, output_format='pandas') symbol = 'NSE:RELIANCE' df, meta_data = ts.get_daily_adjusted(symbol=symbol, outputsize='compact') renames = { '1. open': 'open', '2. high': 'high', '3. low': 'low', '4. close': 'close', '5. adjusted close': 'adjusted close', '6. volume': 'volume', '7. dividend amount': 'dividend amount', '8. split coefficient': 'split coefficient' } df.rename(columns=renames, inplace=True) df.to_csv('tmp.csv') df = pd.read_csv('tmp.csv') renko = stocktrends.Renko(df) renko.brick_size = 9.5 r = renko.get_bricks()
def get_stock(): ## ---- CONFIGURATION ---- # read the config file config = cf.ConfigParser() config.read("config.ini") # get the values from the config file path = config['Dataloading']['filename'] save = config['Dataloading']['save'] filename = config['Dataloading']['save_filename'] load = config['Dataloading']['load'] # checks if data should be downloaded from quandl # print(load) if load == "1" or load == "2": # checks if file with api_key does exist if os.path.isfile("API_Key/api_key.txt"): f = open("API_Key/api_key.txt", "r") userAPI_1 = f.read() # two keys are needed, if this does not work, asks for two keys and overwrites the file try: userAPI, alpha = userAPI_1.split(sep=",") f.close() except ValueError: # the file should still be open in read mode, so it should be closed first f.close() # open the file in write mode f = open("API_Key/api_key.txt", "w+") print("At least one key was not found\n") userAPI = input("Please insert your key for Quandl\n> ") alpha = input("Please insert your key for alphavantage\n> ") # combine the keys to one string, separated by a comma and save it to a file keys = userAPI + "," + alpha f.write(keys) f.close() # if file does not exist, ask user for the key and save the key to a text file else: userAPI = input("> Please insert a valid API key for Quandl\n> ") alpha = input( "> Please insert a valid API key for alphavantage\n> ") # checks if the needed directory exist if not os.path.isdir("API_Key"): # creates the directory if it does not exist os.mkdir("API_Key") f = open("API_Key/api_key.txt", "w") # creates a variable with the two keys, separated and saves it to a file keys = userAPI + "," + alpha f.write(keys) f.close() # Set up Quandl quandl.ApiConfig.api_key = userAPI # ---- INPUTS ----- ticker = str(input("Please enter a Ticker:\n> ")) # while loop runs until a correct start and end date is inserted while True: try: print( "Enter the required dates using the following format: 'dd/mm/YYYY'" ) start = str(input("Starting date:\n> ")) end = str( input( "Ending date. For today's day, please type 'today':\n> " )) # Check the validity of the inputs # Checks if the start/end have a / element + if length of each element is ok print("Thanks, we are procedding your inputs...\n") # Transfrom into date objects start = dt.datetime.strptime(start, "%d/%m/%Y") if end == "today": end = dt.datetime.today() else: end = dt.datetime.strptime(end, "%d/%m/%Y") break except ValueError: print("You entered a wrong time. Please try again \n") print("Selected ticker: " + str(ticker)) print("Starting date is: " + str(start)) print("Ending date is: " + str(end) + "\n") # ---- Get the Data ---- if load == "1": data = quandl.get_table( 'WIKI/PRICES', ticker=ticker, qopts={'columns': ['ticker', 'date', 'adj_close']}, date={ 'gte': start, 'lte': end }, paginate=True) # Turn the data into a Pandas DataFrame data = pd.DataFrame(data) # saves the file if user wants it if save == "1": data.to_csv("data/" + filename + ".txt") print("Here's what the data look like:\n") print(data.head()) # Set the date as index data = data.set_index('date') del data['ticker'] # Rename the column data.columns.values[0] = 'close' # loads the file from the local directory if user wants it elif load == "2": data1 = TimeSeries(key=alpha, output_format='pandas') data1, waste = data1.get_daily_adjusted(symbol=ticker, outputsize='full') data = pd.DataFrame(columns=['close']) data['close'] = data1['5. adjusted close'] # from https://stackoverflow.com/a/40815950 data.index = pd.to_datetime(data.index) # saves the file if user wants it if save == "1": data.to_csv("data/" + filename + ".txt") # Select starting and ending dates data = data.loc[(data.index >= start) & (data.index <= end), :] print(data.head()) else: data = pd.read_csv("data/" + path + ".txt") data = pd.DataFrame(data) # tires to delete None column try: del data['None'] except KeyError: pass # converts date to datetime data['date'] = pd.to_datetime(data['date']) print("Here's what the data look like:\n") print(data.head()) # Set the date as index data = data.set_index('date') # deletes ticker column if existing try: del data['ticker'] except KeyError: pass # Sort from old to new data = data.sort_index() # print("\n With date as index") # print(data.info()) # ---- CONTROLS ---- # Controlling for data size # If too small, poor forecasts and problems with Moving averages # Not able to compute 35 days moving average for example if len(data) <= 250: print( 'ATTENTION: small amount of data points might cause problems to the moving average computations.' ) # ---- RETURN ---- return data