Exemple #1
0
def simulate_ema_strategy(df, symbol, market="us", reload=False):
    df = data_loader.load_price_history(symbol, start, now, market="us", reload=reload)

    directory = f"data/{market}/ema_sim/{start.strftime('%Y-%m-%d')}"
    if not os.path.exists(directory):
        os.makedirs(directory)

    if len(df) == 0:
        return np.nan

    smas_min = [3, 5, 8, 10, 12, 15]
    smas_max = [30, 35, 40, 45, 50, 60]
    smas_used = smas_min + smas_max
    len_cols = len(df.columns)

    for sma in smas_used:
        df[f"ema_{sma}"] = np.round(df.loc[:, "Adj Close"].rolling(window=sma).mean(), 2)
    pos = 0
    num = 0
    percent_change = []
    bp = 0
    for i in range(len(df)):
        c_min = np.min(df.iloc[i, len_cols:len_cols + len(smas_min)])
        c_max = np.max(df.iloc[i, len_cols + len(smas_min):len_cols + len(smas_min) + len(smas_max)])
        close = df["Adj Close"].iloc[i]
        if c_min > c_max:
            if pos == 0:
                bp = close
                pos = 1
        elif c_min < c_max:
            if pos == 1:
                pos = 0
                sp = close
                pc = (sp / bp - 1) * 100
                percent_change.append(pc)

        if num >= len(df) and pos == 1:
            pos = 0
            sp = close
            pc = (sp / bp - 1) * 100
            percent_change.append(pc)

        num += 1
    gains = 0
    num_gains = 0
    losses = 0
    num_losses = 0
    total_return = 1
    for i in percent_change:
        if i > 0:
            gains += i
            num_gains += 1
        else:
            losses += i
            num_losses += 1
        total_return = total_return * ((i / 100) + 1)

    total_return = round((total_return - 1) * 100, 2)

    return total_return
Exemple #2
0
def save_charts(df, period_months=24, moving_averages=(20, 50, 100, 200)):
    if period_months <= 12:
        chart_type = "candlestick"
    else:
        chart_type = "line"

    width, height = 11.69, 8.27

    with PdfPages(f'all_screened_charts_{period_months}_months.pdf') as pdf:

        first_page = plt.figure(figsize=(width, height))
        first_page.clf()
        txt = f"{len(df)} {chart_type} charts\nLast {period_months} months with {moving_averages} moving averages\n" \
              f"{today.strftime('%d %B %Y')}"
        first_page.text(0.5,
                        0.5,
                        txt,
                        transform=first_page.transFigure,
                        size=24,
                        ha="center")
        pdf.savefig()
        plt.close()

        for index, row in df.iterrows():

            symbol = row["Symbol"]
            name = row["Security"]

            div_rate_str = f"{row['dividendRate']}"

            if div_rate_str == "nan":
                div_rate_str = f", div. rate = 0"
            else:
                div_rate_str = f", div. rate = {row['dividendRate']:.4f}"

            title = f"\n\n\n{name} ({symbol})\nCurrent close = {row['Current Close']:.2f}\nRSI = {row['RSI']:.2f} " \
                    f"{div_rate_str}, 50 day MA = {row['50 Day MA']:.2f}"

            df = data_loader.load_price_history(symbol)

            fig, ax = mpf.plot(
                df[df.index >= today - relativedelta(months=period_months)],
                type=chart_type,
                mav=moving_averages,
                volume=True,
                title=title,
                returnfig=True,
                figsize=(width, height))

            ax[0].legend(["Adjusted close"] +
                         [f"{m} MA" for m in moving_averages])

            pdf.savefig(fig)

            plt.close(fig)
Exemple #3
0
msg = EmailMessage()

start = dt.datetime(2018, 12, 1)
now = dt.datetime.now()

stock = "QQQ"
target_price = 180

msg["Subject"] = f"Alert on {stock}"
msg["From"] = email_address
msg["To"] = email_address

alerted = False

df = data_loader.load_price_history(stock, start, now)

current_close = df["Adj Close"][-1]

condition = current_close > target_price

if not alerted and condition:
    message = f"{stock} has activated the alert price of {target_price:.2f}\nCurrent price: {current_close:.2f}"

    print(message)

    msg.set_content(message)

    files = ["old/all_stocks.xlsx"]

    for file in files:
Exemple #4
0
def indicator_chart(symbol,
                    directory,
                    start=dt.datetime(2020, 9, 1),
                    smas=(10, 30, 50, 210),
                    sentiment_value=None,
                    frequency_value=None,
                    prefix=None):
    print(f"Plotting ohlc chart for {symbol}...")

    try:

        start = start - dt.timedelta(days=max(smas))
        now = dt.datetime.now()

        df = data_loader.load_price_history(symbol, start, now)

        if df is None or len(df) == 0:
            print(f"Dataframe is empty for {symbol}.")
            return

        date_delta = df.index[-1] - df.index[0]

        smas = [sma for sma in smas if sma < date_delta.days / 2]

        fig, ax = plt.subplots()
        fig.set_size_inches(18, 9)

        for sma in smas:
            df[f"SMA_{sma}"] = df["Adj Close"].rolling(window=sma).mean()

        # Bollinger bands
        bb_period = 15  # moving average
        std_dev = 2
        df[f"SMA_{bb_period}"] = df["Adj Close"].rolling(
            window=bb_period).mean()
        df["std_dev"] = df["Adj Close"].rolling(window=bb_period).std()
        df["lower_band"] = df[F"SMA_{bb_period}"] - (std_dev * df["std_dev"]
                                                     )  # upper Bollinger band
        df["upper_band"] = df[F"SMA_{bb_period}"] + (std_dev * df["std_dev"]
                                                     )  # lower Bollinger band
        df["Date"] = mdates.date2num(df.index)

        # 10.4.4 stochastic
        period = 10
        K = 4
        D = 4
        df["rol_high"] = df["High"].rolling(
            window=period).max()  # high of period
        df["rol_low"] = df["High"].rolling(
            window=period).min()  # low of period
        df["stok"] = ((df["Adj Close"] - df["rol_low"]) /
                      (df["rol_high"] - df["rol_low"])) * 100  # 10.1
        df["K"] = df["stok"].rolling(window=K).mean()  # 10.4
        df["D"] = df["K"].rolling(window=D).mean()  # 10.4.4
        df["GD"] = df["K"].rolling(window=D).mean()  # green dots
        ohlc = []

        df = df.iloc[max(smas):]

        green_dot_date = []
        green_dot = []
        last_K = 0
        last_D = 0
        last_low = 0
        last_close = 0
        last_low_bb = 0

        # Iterate through price history creating candlesticks and green/blue dots

        for i in df.index:
            candlestick = df["Date"][i], df["Open"][i], df["High"][i], df[
                "Low"][i], df["Adj Close"][i]
            ohlc.append(candlestick)

            # Green dot
            if df["K"][i] > df["D"][i] and last_K < last_D and last_K < 60:

                if 30 in smas and df["High"][i] > df["SMA_30"][i]:
                    color = "chartreuse"
                else:
                    color = "green"

                plt.plot(df["Date"][i],
                         df["High"][i],
                         marker="o",
                         ms=8,
                         ls="",
                         color=color)
                plt.annotate(f"{df['High'][i]:.2f}",
                             (df["Date"][i], df["High"][i]),
                             fontsize=10)

                green_dot_date.append(i)
                green_dot.append(df["High"][i])

                # Lower Bollinger Band Bounce
            if ((last_low < last_low_bb) or
                (df["Low"][i] < df["lower_band"][i])) and (
                    df["Adj Close"][i] > last_close and
                    df["Adj Close"][i] > df["lower_band"][i]) and last_K < 60:
                plt.plot(df["Date"][i],
                         df["Low"][i],
                         marker="o",
                         ms=8,
                         ls="",
                         color="deepskyblue")  # plot blue dot
                plt.annotate(f"{df['Low'][i]:.2f}",
                             (df["Date"][i], df["Low"][i]),
                             xytext=(-10, 7),
                             fontsize=10)

                # store values
            last_K = df["K"][i]
            last_D = df["D"][i]
            last_low = df["Low"][i]
            last_close = df["Adj Close"][i]
            last_low_bb = df["lower_band"][i]

        # Plot moving averages and BBands
        sma_colors = ["cyan", "magenta", "yellow", "orange"]
        for i, sma in enumerate(
                smas
        ):  # This for loop calculates the EMAs for te stated periods and appends to dataframe
            df[f"SMA_{sma}"].plot(label=f"{sma} SMA", color=sma_colors[i])
        df["upper_band"].plot(label="Upper Band",
                              color="dimgray",
                              linestyle=":")
        df["lower_band"].plot(label="Lower Band",
                              color="dimgray",
                              linestyle=":")

        # plot candlesticks
        candlestick_ohlc(ax,
                         ohlc,
                         width=0.75,
                         colorup="w",
                         colordown="r",
                         alpha=0.75)

        ax.xaxis.set_major_formatter(
            mdates.DateFormatter("%B %d"))  # change x axis back to datestamps
        ax.xaxis.set_major_locator(
            mticker.MaxNLocator(8))  # add more x axis labels
        plt.tick_params(axis="x", rotation=45)  # rotate dates for readability

        # Pivot Points
        pivots = []  # Stores pivot values
        dates = []  # Stores Dates corresponding to those pivot values
        counter = 0  # Will keep track of whether a certain value is a pivot
        lastPivot = 0  # Will store the last Pivot value

        value_range = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        date_range = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

        for i in df.index:

            current_max = max(value_range, default=0)
            value = np.round(df["High"][i], 2)

            value_range = value_range[1:9]
            date_range = date_range[1:9]

            value_range.append(value)
            date_range.append(i)

            if current_max == max(value_range, default=0):
                counter += 1
            else:
                counter = 0

            if counter == 5:
                last_pivot = current_max
                date_loc = value_range.index(last_pivot)
                last_date = date_range[date_loc]

                pivots.append(last_pivot)
                dates.append(last_date)

        timeD = dt.timedelta(days=30)  # Sets length of dotted line on chart

        for index in range(len(pivots)):  # Iterates through pivot array

            # print(str(pivots[index])+": "+str(dates[index])) #Prints Pivot, Date couple
            plt.plot_date(
                [dates[index] - (timeD * .075), dates[index] + timeD
                 ],  # Plots horizontal line at pivot value
                [pivots[index], pivots[index]],
                linestyle="--",
                linewidth=2,
                marker=",",
                color="chartreuse")
            plt.annotate(str(pivots[index]),
                         (mdates.date2num(dates[index]), pivots[index]),
                         xytext=(-10, 7),
                         textcoords="offset points",
                         fontsize=14,
                         arrowprops=dict(arrowstyle="simple"))

        plt.xlabel("Date")  # set x axis label
        plt.ylabel("Price")  # set y axis label

        if sentiment_value is not None and frequency_value is not None:
            plt.title(
                f"{sentiment_charts.stock_label(symbol)} - daily indicator chart - "
                f"sentiment = {sentiment_value:.2f}, frequency = {frequency_value*100:.2f}%"
            )
        else:
            plt.title(
                f"{sentiment_charts.stock_label(symbol)} - daily indicator chart"
            )
        plt.ylim(df["Low"].min(), df["High"].max() * 1.05)  # add margins
        # plt.yscale("log")
        plt.legend(loc="upper left")

        plt.grid()

        if prefix is not None:
            prefix_str = f"{prefix}_"
        else:
            prefix_str = ""

        file_path = f"public_html/finance/res/img/ohlc/{directory}"

        if not os.path.exists(file_path):
            os.makedirs(file_path)

        plt.savefig(f"{file_path}/{prefix_str}{symbol}_ohlc.png", dpi=150)

        plt.close(fig)
        plt.clf()

    except ValueError:
        print("ValueError for " + symbol)
        return
Exemple #5
0
def screen_stock(symbol, market="us", reload=False, remove_screened=True):
    print(symbol)

    try:
        df = data_loader.load_price_history(symbol,
                                            reload=reload,
                                            market=market)

        if df is None:
            raise ValueError

        if not reload and len(df) > 0 and isinstance(
                df.index[-1], dt.datetime) and not (
                    (end_date.weekday() >= 5
                     and df.index[-1] >= end_date - dt.timedelta(days=3)) or
                    (end_date.weekday() < 5
                     and df.index[-1] >= end_date - dt.timedelta(days=2))):
            df = data_loader.load_price_history(symbol, reload=True)

        if df is None or len(df) == 0:
            raise ValueError
    except ValueError:
        print(f"{symbol} not found.")
        return None

    smas_used = [50, 150, 200]
    for sma in smas_used:
        df[f"SMA_{sma}"] = np.round(df["Adj Close"].rolling(window=sma).mean(),
                                    2)

    current_close = df["Adj Close"].iloc[-1]
    moving_average_50 = df["SMA_50"].iloc[-1]
    moving_average_150 = df["SMA_150"].iloc[-1]
    moving_average_200 = df["SMA_200"].iloc[-1]

    try:
        low_of_52_week = np.min(df["Adj Close"].iloc[-260:])
        high_of_52_week = np.max(df["Adj Close"].iloc[-260:])

        rs_rating = rsi(df)
    except IndexError:
        return None

    try:
        moving_average_200_20 = df["SMA_200"].iloc[-20]
    except IndexError:
        moving_average_200_20 = 0

    # Condition 1: Current Price > 150 SMA and > 200 SMA
    cond_1 = current_close > moving_average_150 > moving_average_200
    # Condition 2: 150 SMA > 200 SMA
    cond_2 = moving_average_150 > moving_average_200
    # Condition 3: 200 SMA trending up for at least 1 month (ideally 4-5 months)
    cond_3 = moving_average_200 > moving_average_200_20
    # Condition 4: 50 SMA > 150 SMA and 150 SMA > 200 SMA
    cond_4 = moving_average_50 > moving_average_150 > moving_average_200
    # Condition 5: Current Price > 50 SMA
    cond_5 = current_close > moving_average_50
    # Condition 6: Current Price is at least 30% above 52 week low (Many of the best are up 100-300% before
    # coming out of consolidation)
    cond_6 = current_close >= (1.3 * low_of_52_week)
    # Condition 7: Current Price is within 25% of 52 week high
    cond_7 = current_close >= (0.75 * high_of_52_week)
    # Condition 8: IBD RS rating >70 and the higher the better
    cond_8 = rs_rating > 70

    is_screened = (cond_1 and cond_2 and cond_3 and cond_4 and cond_5
                   and cond_6 and cond_7 and cond_8)

    if remove_screened and not is_screened:
        return None

    if is_screened:
        is_screened_str = "PASS"
    else:
        is_screened_str = "FAIL"

    info_dict = data_loader.load_ticker_info(symbol,
                                             type_str="info",
                                             reload=reload)

    if info_dict is None:
        info_dict = {}

    for key in ["dividendRate", "dividendYield", "payoutRatio"]:
        if key not in info_dict:
            info_dict[key] = np.nan
        elif info_dict[key] is None:
            info_dict[key] = np.nan
        elif key == "dividendRate":
            info_dict[key] = np.round(info_dict[key], 2)
        else:
            info_dict[key] = np.round(info_dict[key], 4)

    for key in ["longName", "sector"]:
        if key not in info_dict:
            info_dict[key] = ""
        elif info_dict[key] is None:
            info_dict[key] = ""

    row = {
        "Security":
        info_dict["longName"],
        "Symbol":
        symbol.upper(),
        "Sector":
        info_dict["sector"],
        "RSI":
        np.round(rs_rating, 2),
        "Mark Minervini test":
        is_screened_str,
        "Current Close":
        np.round(current_close, 2),
        "div. Rate":
        info_dict["dividendRate"],
        "div. Yield":
        info_dict["dividendYield"],
        "Payout Ratio":
        info_dict["payoutRatio"],
        "Simulation % Return":
        simulator.simulate_ema_strategy(df,
                                        symbol,
                                        market=market,
                                        reload=reload),
        "50 Day MA":
        moving_average_50,
        "150 Day MA":
        moving_average_150,
        "200 Day MA":
        moving_average_200,
        "52 Week Low":
        low_of_52_week,
        "52 Week High":
        high_of_52_week,
    }

    for k, v in info_dict.items():
        if k not in cols_to_remove and v is not None:
            # type(v)
            # if k == "longBusinessSummary":
            #     row[k] = v.split('.')[0]
            # else:
            row[k] = v

    return row
Exemple #6
0
import datetime as dt

import matplotlib.pyplot as plt
import numpy as np

import data_loader

start = dt.datetime(2019, 6, 1)
now = dt.datetime.now()

df = data_loader.load_price_history("amd", start, now)

df["High"].plot(label="High")

pivots = []
dates = []
counter = 0
last_pivot = 0

value_range = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
date_range = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

for i in df.index:

    current_max = max(value_range, default=0)
    value = np.round(df["High"][i], 2)

    value_range = value_range[1:9]
    date_range = date_range[1:9]

    value_range.append(value)
Exemple #7
0
import datetime as dt

import matplotlib.pyplot as plt
import mplfinance as mpf
import numpy as np
import pandas as pd

import data_loader as dl

now = dt.datetime.today()

df = dl.load_price_history("aapl", start_date=dt.datetime(2018, 1, 1))

df.drop(df[df["Volume"] < 1000].index, inplace=True)

df_monthly = dl.monthly(df)

# GLV: green line value

gl_date = 0
last_glv = 0
current_date = None
current_glv = 0
counter = 0

glv_list = []
gl_date_list = []

for index, value in df_monthly["High"].items():
    if value > current_glv:
        current_glv = value