import pandas as pd
import numpy as np
import os
import gc
import copy
from pathlib import Path
from datetime import datetime, timedelta, time, date
#this package is to download equity price data from yahoo finance
#the source code of this package can be found here: https://github.com/ranaroussi/yfinance/blob/main
import yfinance as yf
pd.options.display.max_rows = 100
pd.options.display.max_columns = 100
import warnings
warnings.filterwarnings("ignore")
import pytorch_lightning as pl
random_seed=1234
pl.seed_everything(random_seed)
Global seed set to 1234
1234
##### Download data#S&P 500 (^GSPC), Dow Jones Industrial Average (^DJI), NASDAQ Composite (^IXIC)
#Russell 2000 (^RUT), Crude Oil Nov 21 (CL=F), Gold Dec 21 (GC=F)
#Treasury Yield 10 Years (^TNX)
#CBOE Volatility Index (^VIX) Chicago Options - Chicago Options Delayed Price. Currency in USD
#benchmark_tickers = ['^GSPC', '^DJI', '^IXIC', '^RUT', 'CL=F', 'GC=F', '^TNX']
benchmark_tickers = ['^GSPC', '^VIX']
tickers = benchmark_tickers + ['GSK', 'BST', 'PFE']
#https://github.com/ranaroussi/yfinance/blob/main/yfinance/base.py
# def history(self, period="1mo", interval="1d",
# start=None, end=None, prepost=False, actions=True,
# auto_adjust=True, back_adjust=False,
# proxy=None, rounding=False, tz=None, timeout=None, **kwargs):
dfs = {}
for ticker in tickers:
cur_data = yf.Ticker(ticker)
hist = cur_data.history(period="max", start='2000-01-01')
print(datetime.now(), ticker, hist.shape, hist.index.min(), hist.index.max())
dfs[ticker] = hist
2022-09-10 19:00:08.298576 ^GSPC (5710, 7) 1999-12-31 00:00:00 2022-09-09 00:00:00
2022-09-10 19:00:08.689645 ^VIX (5710, 7) 1999-12-31 00:00:00 2022-09-09 00:00:00
2022-09-10 19:00:09.066685 GSK (5710, 7) 1999-12-31 00:00:00 2022-09-09 00:00:00
2022-09-10 19:00:09.381786 BST (1980, 7) 2014-10-29 00:00:00 2022-09-09 00:00:00
2022-09-10 19:00:09.814302 PFE (5710, 7) 1999-12-31 00:00:00 2022-09-09 00:00:00
ticker = 'PFE'
dfs[ticker].tail(5)
Open | High | Low | Close | Volume | Dividends | Stock Splits | |
---|---|---|---|---|---|---|---|
Date | |||||||
2022-09-02 | 46.740002 | 46.799999 | 45.529999 | 45.700001 | 14662700 | 0.0 | 0.0 |
2022-09-06 | 45.959999 | 46.439999 | 45.529999 | 45.759998 | 17153500 | 0.0 | 0.0 |
2022-09-07 | 45.700001 | 46.209999 | 45.380001 | 46.130001 | 15378900 | 0.0 | 0.0 |
2022-09-08 | 46.020000 | 47.119999 | 45.869999 | 47.080002 | 18271000 | 0.0 | 0.0 |
2022-09-09 | 47.200001 | 47.990002 | 47.099998 | 47.840000 | 17501700 | 0.0 | 0.0 |
"""
Function: __C_Crow
// _C_Crow Function
// TASC OCT 2017
// A Candlestick Strategy
// With Soldiers and Crows
// D'Ambrosio and Star
_C_Crow = Close[1] > Close[2] and
Close[1] > Open[1] and
Open < Close[1] and
Close < Open[1] and
Open > Open[1] and
Close[1] > Close[2] and
Close[2] > Close[3] ;
"""
"""
One Black Crow:
minPrice:= 10; {minimum price}
minVol:= 100000; {minimum volume}
trend:= Sum( C > Ref(C, -1), 3) = 3;
Ref(C > O, -1) AND O < Ref(C, -1) AND
C < Ref(O, -1) AND O > Ref(O, -1) AND
Ref(trend, -1) AND C > minPrice AND
Mov(V, 50, S) > minVol
"""
def _scan_crow(c, o):
crow_ = True
crow_ = crow_ & (c.shift(1)>c.shift(2))
crow_ = crow_ & (c.shift(1)>o.shift(1))
crow_ = crow_ & (o<c.shift(1))
crow_ = crow_ & (c<o.shift(1))
crow_ = crow_ & (o>o.shift(1))
crow_ = crow_ & (c.shift(2)>c.shift(3))
return crow_
"""
Function: _C_Soldier
// _C_Soldier Function
// TASC OCT 2017
// A Candlestick Strategy
// With Soldiers and Crows
// D'Ambrosio and Star
_C_Soldier = Close[1] < Close[2] and
Close[1] < Open[1] and
Open > Close[1] and
Close > Open[1] and
Open < Open[1] and
Close[1] < Close[2] and
Close[2] < Close[3] ;
"""
"""
One White Soldier:
minPrice:= 1; {minimum price}
minVol:= 100000; {minimum volume}
trend:= Sum( C < Ref(C, -1), 3) = 3;
Ref(C < O, -1) AND O > Ref(C, -1) AND
C > Ref(O, -1) AND O < Ref(O, -1) AND
Ref(trend, -1) AND C > minPrice AND
Mov(V, 50, S) > minVol
"""
def _scan_soldier(c, o):
soldier_ = True
soldier_ = soldier_ & (c.shift(1)<c.shift(2))
soldier_ = soldier_ & (c.shift(1)<o.shift(1))
soldier_ = soldier_ & (o>c.shift(1))
soldier_ = soldier_ & (c>o.shift(1))
soldier_ = soldier_ & (o<o.shift(1))
soldier_ = soldier_ & (c.shift(2)<c.shift(3))
return soldier_
from core.finta import TA
df = dfs[ticker][['Open', 'High', 'Low', 'Close', 'Volume']]
df = df.round(2)
df_ref = dfs['^GSPC'][[ 'Close']]
df_ref = df_ref.round(2)
df_ref.columns = ['ref_close']
print(df.shape, df_ref.shape)
df = df.merge(df_ref, left_index=True, right_index=True, how='inner')
print(df.shape)
df.isna().sum()
(5710, 5) (5710, 1)
(5710, 6)
Open 0
High 0
Low 0
Close 0
Volume 0
ref_close 0
dtype: int64
df_ta = TA.BBANDS(df, period = 20, std_multiplier=2.2, column="close")
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
df_ta = TA.XSII(df, slow_period = 102, fast_period = 7)
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
df_ta = TA.RSMK(df, rsmk_period = 60, ema_period = 5, column = "close", ref_column = "ref_close")
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
df_ta = TA.SQZMI(df, period = 20, column = "close")
df['SQZMI'] = df_ta
del df_ta
gc.collect()
38
df['SOLDIER'] = _scan_soldier(df['Close'], df['Open'])
df['CROW'] = _scan_crow(df['Close'], df['Open'])
df_ta = TA.SMA(df, period = 50, column = "volume")
df['MAV'] = df_ta.values
df[['SOLDIER', 'CROW', 'SQZMI']].value_counts()
SOLDIER CROW SQZMI
False False False 4865
True 682
True False False 80
False True False 63
True False True 11
False True True 9
dtype: int64
min_avg_volume = 100000
df['B'] = (df['SOLDIER'] & (df['MAV']>min_avg_volume)).astype(int)*((df['High'] + df['Low'])/2)
df['S'] = (df['CROW'] & (df['MAV']>min_avg_volume)).astype(int)*((df['High'] + df['Low'])/2)
df['B2'] = (df['SOLDIER'] & (df['MAV']>min_avg_volume) & df['SQZMI']).astype(int)*((df['High'] + df['Low'])/2)
display(df.head(5))
display(df.tail(5))
Open | High | Low | Close | Volume | ref_close | BB_UPPER | BB_MIDDLE | BB_LOWER | BBWIDTH | PERCENT_B | XSII1 | XSII2 | XSII3 | XSII4 | RSMK | SQZMI | SOLDIER | CROW | MAV | B | S | B2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||||||||||||
1999-12-31 | 14.25 | 14.31 | 14.11 | 14.22 | 5939817 | 1469.25 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 15.2154 | 13.2246 | NaN | False | False | False | NaN | 0.0 | 0.0 | 0.0 |
2000-01-03 | 14.06 | 14.20 | 13.87 | 13.98 | 12873345 | 1455.22 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 14.9586 | 13.0014 | NaN | False | False | False | NaN | 0.0 | 0.0 | 0.0 |
2000-01-04 | 13.70 | 13.81 | 13.16 | 13.46 | 14208974 | 1399.42 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 14.4022 | 12.5178 | NaN | False | False | False | NaN | 0.0 | 0.0 | 0.0 |
2000-01-05 | 13.54 | 13.98 | 13.51 | 13.68 | 12981591 | 1402.11 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 14.6376 | 12.7224 | NaN | False | False | False | NaN | 0.0 | 0.0 | 0.0 |
2000-01-06 | 13.70 | 14.36 | 13.68 | 14.17 | 11115273 | 1403.45 | NaN | NaN | NaN | NaN | NaN | 14.17851 | 13.62249 | 15.1619 | 13.1781 | NaN | False | False | False | NaN | 0.0 | 0.0 | 0.0 |
Open | High | Low | Close | Volume | ref_close | BB_UPPER | BB_MIDDLE | BB_LOWER | BBWIDTH | PERCENT_B | XSII1 | XSII2 | XSII3 | XSII4 | RSMK | SQZMI | SOLDIER | CROW | MAV | B | S | B2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||||||||||||
2022-09-02 | 46.74 | 46.80 | 45.53 | 45.70 | 14662700 | 3924.26 | 51.663455 | 48.1505 | 44.637545 | 0.145916 | 0.151220 | 46.90878 | 45.06922 | 52.314323 | 45.469459 | -10.218471 | False | False | False | 17821424.0 | 0.0 | 0.0 | 0.0 |
2022-09-06 | 45.96 | 46.44 | 45.53 | 45.76 | 17153500 | 3908.19 | 51.579166 | 47.9600 | 44.340834 | 0.150924 | 0.196063 | 46.81800 | 44.98200 | 52.168463 | 45.342683 | -9.751431 | False | False | False | 17677630.0 | 0.0 | 0.0 | 0.0 |
2022-09-07 | 45.70 | 46.21 | 45.38 | 46.13 | 15378900 | 3979.87 | 51.374440 | 47.7775 | 44.180560 | 0.150570 | 0.270986 | 46.81800 | 44.98200 | 52.061739 | 45.249923 | -9.580215 | False | False | False | 17662122.0 | 0.0 | 0.0 | 0.0 |
2022-09-08 | 46.02 | 47.12 | 45.87 | 47.08 | 18271000 | 4006.18 | 51.062513 | 47.6340 | 44.205487 | 0.143952 | 0.419207 | 47.08677 | 45.24023 | 52.031775 | 45.223879 | -8.916949 | False | False | False | 17699184.0 | 0.0 | 0.0 | 0.0 |
2022-09-09 | 47.20 | 47.99 | 47.10 | 47.84 | 17501700 | 4067.36 | 51.025194 | 47.6115 | 44.197806 | 0.143398 | 0.533468 | 47.37849 | 45.52051 | 52.030341 | 45.222633 | -8.579216 | False | False | False | 17770704.0 | 0.0 | 0.0 | 0.0 |
df.columns
Index(['Open', 'High', 'Low', 'Close', 'Volume', 'ref_close', 'BB_UPPER',
'BB_MIDDLE', 'BB_LOWER', 'BBWIDTH', 'PERCENT_B', 'XSII1', 'XSII2',
'XSII3', 'XSII4', 'RSMK', 'SQZMI', 'SOLDIER', 'CROW', 'MAV', 'B', 'S',
'B2'],
dtype='object')
from core.visuals import *
start = -1500
end = df.shape[0]
# df_sub = df.iloc[start:end]
df_sub = df[(df.index<='2016-06-02') & (df.index>='2015-09-02')]
names = {'main_title': f'{ticker}'}
lines0 = basic_lines(df_sub[['XSII1', 'XSII2', 'XSII3', 'XSII4']],
colors = [],
**dict(panel=0, width=1.5, secondary_y=False))
lines1 = basic_lines(df_sub[['RSMK']],
colors = ['cadetblue'],
**dict(panel=1, width=1, secondary_y=False))
lines3 = basic_lines(df_sub[[ 'S']],
colors = ['black'],
**dict(panel=0, type='scatter', marker=r'${S}$' , markersize=100, secondary_y=False))
lines2 = basic_lines(df_sub[[ 'B', 'B2']],
colors = ['navy', 'red'],
**dict(panel=0, type='scatter', marker=r'${B}$' , markersize=100, secondary_y=False))
lines_ = dict(**lines0, **lines1)
lines_.update(lines2)
lines_.update(lines3)
shadows_ = basic_shadows(bands=[-5, 5], nsamples=df_sub.shape[0], **dict(panel=1, color="lightskyblue",alpha=0.1,interpolate=True))
fig_config_ = dict(figratio=(18,10), volume=False, volume_panel=2,panel_ratios=(5,2), tight_layout=True, returnfig=True,)
ax_cfg_ = {0:dict(basic=[6, 2, ['XSII1', 'XSII2', 'XSII3', 'XSII4']],
title=dict(label = 'XSII', fontsize=9, style='italic', loc='left'),
),
2:dict(basic=[1, 0, ['RSMK']]
),
}
names = {'main_title': f'{ticker}'}
aa_, bb_ = make_panels(main_data = df_sub[['Open', 'High', 'Low', 'Close', 'Volume']],
added_plots = lines_,
fill_betweens = shadows_,
fig_config = fig_config_,
axes_config = ax_cfg_,
names = names)