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()
Example #2
0
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
Example #5
0
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]
Example #6
0
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
Example #7
0
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"],
Example #9
0
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()
Example #10
0
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')
Example #11
0
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
Example #13
0
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={
Example #14
0
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:
Example #16
0
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)
Example #17
0
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
Example #18
0
#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
Example #19
0
    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
Example #24
0
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
Example #26
0
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
Example #27
0
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"
    )
Example #28
0
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()
Example #29
0
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()
Example #30
0
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