File size: 8,951 Bytes
dd55947
d2e4d0a
 
 
 
 
 
 
b2f8372
 
dd55947
 
b2f8372
7237f65
b2f8372
 
 
d2e4d0a
7237f65
b2f8372
 
dd55947
39d5cfb
61c5904
dd55947
b2f8372
 
 
 
 
 
dd55947
b2f8372
 
dd55947
b2f8372
 
 
 
 
dd55947
b2f8372
 
 
 
 
d2e4d0a
39d5cfb
b2f8372
 
 
 
a6513d3
ac64c34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d77ae08
 
 
 
 
 
 
 
 
dd55947
d77ae08
 
dd55947
d77ae08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17d34c4
 
 
 
d77ae08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e0683b
17d34c4
d77ae08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17d34c4
 
 
 
d77ae08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e0683b
17d34c4
d2e4d0a
 
 
b2f8372
d2e4d0a
 
 
7237f65
39d5cfb
b2f8372
 
 
 
 
 
dd55947
 
b2f8372
 
 
d2e4d0a
dd55947
 
b2f8372
 
 
 
7237f65
3f31e32
 
b2f8372
fb58fcb
ac64c34
b2f8372
 
d2e4d0a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

import pandas as pd
import panel as pn
from datetime import datetime
from datetime import date
pn.extension('bokeh', template='bootstrap')
import hvplot.pandas

import pandas as pd
import yfinance as yf
import panel as pn

@pn.cache
def get_df(ticker, startdate , enddate , interval="1d",window=50,window2=150):
    # interval="1d"
    # get_df(ticker ="PG", startdate="2000-01-01" , enddate="2023-09-01" , interval="1d")
    DF = yf.Ticker(ticker).history(start=startdate,end=enddate,interval=interval)
    DF['SMA'] = DF.Close.rolling(window=window).mean()
    DF['SMA2'] = DF.Close.rolling(window=window2).mean()
    DF = DF.reset_index()
    return DF 

def get_hvplot(ticker , startdate , enddate , interval,window,window2):
    DF = get_df(ticker , startdate=startdate , enddate=enddate , interval=interval,window=window,window2=window2)

    import hvplot.pandas  # Ensure hvplot is installed (pip install hvplot)
    from sklearn.linear_model import LinearRegression
    import holoviews as hv
    hv.extension('bokeh')
    # Assuming your dataframe is named 'df' with columns 'Date' and 'Close'
    # If not, replace 'Date' and 'Close' with your actual column names.

    # Step 1: Create a scatter plot using hvplot
    scatter_plot = DF.hvplot(x='Date', y='Close',  kind='scatter',title=f'{ticker} Close vs. Date')

    # Step 2: Fit a linear regression model
    DF['Date2'] = pd.to_numeric(DF['Date'])
    X = DF[['Date2']]
    y = DF[['Close']] #.values
    model = LinearRegression().fit(X, y)

    # # Step 3: Predict using the linear regression model
    DF['Predicted_Close'] = model.predict(X)

    # # Step 4: Create a line plot for linear regression
    line_plot = DF.hvplot(x='Date', y='Predicted_Close', kind='line',line_dash='dashed', color='red')
    line_plot_SMA = DF.hvplot(x='Date', y='SMA', kind='line',line_dash='dashed', color='orange')
    line_plot_SMA2 = DF.hvplot(x='Date', y='SMA2', kind='line',line_dash='dashed', color='orange')

    # # Step 5: Overlay scatter plot and linear regression line
    # return (scatter_plot * line_plot).opts(width=800, height=600, show_grid=True, gridstyle={ 'grid_line_color': 'gray'})
    # grid_style = {'grid_line_color': 'black'}#, 'grid_line_width': 1.5, 'ygrid_bounds': (0.3, 0.7),'minor_xgrid_line_color': 'lightgray', 'xgrid_line_dash': [4, 4]}
    return (scatter_plot * line_plot *line_plot_SMA *line_plot_SMA2).opts(width=800, height=600, show_grid=True)
def get_income_statement_df(ticker):
    yfobj = yf.Ticker(ticker)
    df= yfobj.financials.T
    df.index = pd.to_datetime(df.index, format='%Y-%m-%d')
    return df

def get_income_hvplot(ticker):
    DF = get_income_statement_df(ticker)
    plt1 = DF.hvplot.line(y='Total Revenue') * DF.hvplot.scatter(y='Total Revenue').opts(color="red") 
    plt1.opts(width=600, height=450, show_grid=True)
    plt2 = DF.hvplot.line(y='Gross Profit') * DF.hvplot.scatter(y='Gross Profit').opts(color="red") 
    plt2.opts(width=600, height=450, show_grid=True)
    plt3 = DF.hvplot.line(y='Net Income') * DF.hvplot.scatter(y='Net Income').opts(color="red")
    plt3.opts(width=600, height=450, show_grid=True)
    return pn.Column(plt1 , plt2 , plt3 )
    # return ( DF.hvplot.line(y='Net Income') * DF.hvplot.scatter(y='Net Income').opts(color="red") )+ (DF.hvplot.line(y='Gross Profit') * DF.hvplot.scatter(y='Gross Profit').opts(color="red") )+ 
    # (DF.hvplot.line(y='Total Revenue') * DF.hvplot.scatter(y='Total Revenue').opts(color="red") )

def lookup_discountedrate(betavalue):
  betavsdiscountedrate = {1: 5, 1: 6, 1.1: 6.5, 1.2: 7, 1.3: 7.5, 1.4: 8, 1.5: 8.5, 1.6: 9}
  if betavalue < 1:
    return betavsdiscountedrate[1]  # Return the value for key 1 if key is below 1
  elif betavalue > 1.6:
    return betavsdiscountedrate[1.6]  # Return the value for key 1.6 if key is above 1.6
  else:
    # Find the closest key to the given key
    closest_key = min(betavsdiscountedrate.keys(), key=lambda x: abs(x - betavalue))

    # Get the corresponding value
    value = betavsdiscountedrate[closest_key]

    return value


def calc_fairprice_CDF(ticker):
  import yfinance as yf
  yfobj = yf.Ticker(ticker)

  #calculate eps growing next 5 years
  EPSnext5Y = yfobj.get_info()['trailingPE'] / yfobj.get_info()['trailingPegRatio']

  years = 10
  #
  cashflowinitial = yfobj.get_info()['operatingCashflow']

  cashflowlst=[]
  cashflow = cashflowinitial
  for i in range(1,years+1):
    cashflow = cashflow*(1+EPSnext5Y/100)
    cashflowlst.append(cashflow)

  try:
    discountedrate = lookup_discountedrate(yfobj.get_info()['beta'])
  except:
      discountedrate = 5

  discountedfactorlst =[]
  discountedvaluelst=[]
  discountedfactor =1

  for i in range(1,years+1):
    discountedfactor =( 1 / (1+ discountedrate/100)**i)
    discountedfactorlst.append(discountedfactor)
    discountedvalue = discountedfactor * cashflowlst[i-1]
    discountedvaluelst.append(discountedvalue)

  PV10yearsCashFlow =0
  for i in range(0,years):
    PV10yearsCashFlow += discountedvaluelst[i]

  #intrinsic value before cash/debt
  intrinsicvaluebeforecashdebt = PV10yearsCashFlow / yfobj.get_info()['sharesOutstanding']

  debtpershare = yfobj.get_info()['totalDebt'] / yfobj.get_info()['sharesOutstanding']
  cashpershare = yfobj.get_info()['totalCash'] / yfobj.get_info()['sharesOutstanding']
  intrinsicvalue = intrinsicvaluebeforecashdebt + cashpershare - debtpershare

  previousClose = yfobj.get_info()['previousClose']
  deviation = 100*(intrinsicvalue - previousClose) / previousClose
  # return intrinsicvalue , previousClose , deviation
  return pn.Row(pn.widgets.StaticText(name='fairprice_CDF', value=str(round(intrinsicvalue,1)))   ,pn.widgets.StaticText(name='deviation', value=str(round(deviation,2)))    )


def calc_fairprice_DnetP(ticker):
  import yfinance as yf
  yfobj = yf.Ticker(ticker)

  #calculate eps growing next 5 years
  EPSnext5Y = yfobj.get_info()['trailingPE'] / yfobj.get_info()['trailingPegRatio']

  years = 5
  #
  cashflowinitial = yfobj.get_info()['netIncomeToCommon']

  cashflowlst=[]
  cashflow = cashflowinitial
  for i in range(1,years+1):
    cashflow = cashflow*(1+EPSnext5Y/100)
    cashflowlst.append(cashflow)

  try:
      discountedrate = lookup_discountedrate(yfobj.get_info()['beta'])
  except:
      discountedrate = 5

  discountedfactorlst =[]
  discountedvaluelst=[]
  discountedfactor =1

  for i in range(1,years+1):
    discountedfactor =( 1 / (1+ discountedrate/100)**i)
    discountedfactorlst.append(discountedfactor)
    discountedvalue = discountedfactor * cashflowlst[i-1]
    discountedvaluelst.append(discountedvalue)

  PV10yearsCashFlow =0
  for i in range(0,years):
    PV10yearsCashFlow += discountedvaluelst[i]

  #intrinsic value before cash/debt
  intrinsicvaluebeforecashdebt = PV10yearsCashFlow / yfobj.get_info()['sharesOutstanding']

  debtpershare = yfobj.get_info()['totalDebt'] / yfobj.get_info()['sharesOutstanding']
  cashpershare = yfobj.get_info()['totalCash'] / yfobj.get_info()['sharesOutstanding']
  intrinsicvalue = intrinsicvaluebeforecashdebt + cashpershare - debtpershare

  previousClose = yfobj.get_info()['previousClose']
  intrinsicvalue= intrinsicvalue + previousClose

  deviation = 100*(intrinsicvalue - previousClose) / previousClose
  # return intrinsicvalue , previousClose , deviation
  return pn.Row(pn.widgets.StaticText(name='fairprice_DnetP', value=str(round(intrinsicvalue,1)))  , pn.widgets.StaticText(name='deviation', value=str(round(deviation,2)))  ) 
    
# tickers = ['AAPL', 'META', 'GOOG', 'IBM', 'MSFT','NKE','DLTR','DG']
# ticker = pn.widgets.Select(name='Ticker', options=tickers)

tickers = pd.read_csv('tickers.csv').Ticker.to_list()
ticker = pn.widgets.AutocompleteInput(name='Ticker', options=tickers , placeholder='Write Ticker here همین جا')
ticker.value = "AAPL"
window = pn.widgets.IntSlider(name='Window Size', value=50, start=5, end=1000, step=5)
window2 = pn.widgets.IntSlider(name='Window Size2', value=150, start=5, end=1000, step=5)

# Create a DatePicker widget with a minimum date of 2000-01-01
date_start = pn.widgets.DatePicker(
    name ="Start Date",
    description='Select a Date',
    start= date(2000, 1, 1)
)

date_end = pn.widgets.DatePicker(
    name ="End Date",# value=datetime(2000, 1, 1),
    description='Select a Date',
    end= date.today() #date(2023, 9, 1)
)

date_start.value = date(2010,1,1)
date_end.value = date.today()

pn.Row(
    pn.Column( ticker, window , window2, date_start , date_end),
    # pn.bind(calc_fairprice_CDF,ticker),
    # pn.bind(calc_fairprice_DnetP,ticker)),
    # pn.panel(pn.bind(get_hvplot, ticker, "2010-01-01","2023-09-01","1d")) #, sizing_mode='stretch_width')
    pn.panel(pn.bind(get_hvplot, ticker, date_start , date_end,"1d",window,window2)), #, sizing_mode='stretch_width')
    pn.panel(pn.bind(get_income_hvplot, ticker))    #, sizing_mode='stretch_width')    
).servable(title="Under Valued Screener- Linear Regression")