Arkm20 commited on
Commit
0c52e07
1 Parent(s): 3480103

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -32
app.py CHANGED
@@ -4,8 +4,8 @@ import yfinance as yf
4
  from datetime import datetime, timedelta
5
  import requests
6
  from bs4 import BeautifulSoup
7
- from concurrent.futures import ThreadPoolExecutor, as_completed
8
  from pattern_finder import score_downward_trend, score_candle, calculate_risk_reward
 
9
  import urllib3
10
  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
11
 
@@ -29,7 +29,7 @@ def load_sp500_tickers():
29
  def load_data(ticker):
30
  """Load stock data using yfinance."""
31
  end_date = datetime.today()
32
- start_date = end_date - timedelta(days=365) # Get 1 year of data
33
  data = yf.download(ticker, start=start_date, end=end_date)
34
  return data
35
 
@@ -53,13 +53,6 @@ def average_downtrend(data, method, window=4):
53
  return avg_diff if avg_diff < 0 else 0.0
54
 
55
 
56
- def score_candle(candle, prev_candle, trend_strength):
57
- """Score a single candle based on its characteristics and previous candle."""
58
- # [Keep the existing scoring logic]
59
- # ...
60
- return score
61
-
62
-
63
  def score_today_candle(data, window=4):
64
  """Score today's candle based on the downtrend from the past 'window' days."""
65
  if len(data) < window + 1:
@@ -70,6 +63,7 @@ def score_today_candle(data, window=4):
70
 
71
  close_price = today_candle['Close']
72
  previous_data = data.iloc[-(window+1):-1]
 
73
  down_High = average_downtrend(previous_data, method="High", window=window) + average_downtrend(previous_data, method="High", window=7) / 2
74
  down_Close = average_downtrend(previous_data, method="Close", window=window) + average_downtrend(previous_data, method="Close", window=7) / 2
75
  avg_downtrend = (down_High + down_Close) / 2
@@ -82,45 +76,50 @@ def score_today_candle(data, window=4):
82
  sma_20 = calculate_sma(data, window=20).iloc[-1]
83
  ema_10 = calculate_ema(data, window=10).iloc[-1]
84
 
85
- if (close_price < ema_10) or (close_price < sma_20) or (close_price < sma_50) or (close_price < sma_200):
86
  return -1
87
-
88
  return score_candle(today_candle, prev_candle, abs(avg_downtrend))
89
 
90
 
91
- def scan_ticker(ticker):
92
- """Load data for a ticker and calculate its score."""
93
- data = load_data(ticker)
94
- if not data.empty:
95
- score = score_today_candle(data)
96
- if score > 0:
97
- return ticker, score
98
- return None
99
-
100
-
101
  def scan_sp500(top_n=25, progress=gr.Progress()):
102
  tickers = load_sp500_tickers()
 
103
  tickers.append("QQQ")
104
 
105
- scores = []
106
  with ThreadPoolExecutor(max_workers=10) as executor:
107
- futures = {executor.submit(scan_ticker, ticker): ticker for ticker in tickers}
108
- for i, future in enumerate(as_completed(futures), 1):
109
- result = future.result()
110
- if result:
111
- scores.append(result)
112
- progress(i / len(tickers), desc="Processing Tickers")
 
 
 
 
 
 
 
 
113
 
114
  scores = sorted(scores, key=lambda x: x[1], reverse=True)
115
  return scores[:top_n]
116
 
117
 
 
 
 
 
 
 
 
118
  def gradio_scan_sp500(top_n, progress=gr.Progress()):
119
- progress(0, desc="Downloading Data")
120
  tickers = load_sp500_tickers()
121
  tickers.append("QQQ")
122
 
123
- progress(0.3, desc="Running Scanner")
124
  results = scan_sp500(top_n, progress)
125
 
126
  last_data = load_data(results[0][0])
@@ -129,11 +128,12 @@ def gradio_scan_sp500(top_n, progress=gr.Progress()):
129
  date_created = next_market_day.strftime("%Y-%m-%d")
130
 
131
  output = f"Scan Results for Market Open on: {date_created}\n\n"
132
- output += "Top {} stocks based on pattern finder score:\n\n".format(top_n)
133
  for ticker, score in results:
134
- output += "{}: Total Score = {:.2f}\n".format(ticker, score)
135
  return output
136
 
 
137
  iface = gr.Interface(
138
  fn=gradio_scan_sp500,
139
  inputs=gr.Slider(minimum=1, maximum=100, step=1, label="Number of top stocks to display", value=25),
 
4
  from datetime import datetime, timedelta
5
  import requests
6
  from bs4 import BeautifulSoup
 
7
  from pattern_finder import score_downward_trend, score_candle, calculate_risk_reward
8
+ from concurrent.futures import ThreadPoolExecutor, as_completed
9
  import urllib3
10
  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
11
 
 
29
  def load_data(ticker):
30
  """Load stock data using yfinance."""
31
  end_date = datetime.today()
32
+ start_date = end_date - timedelta(days=365)
33
  data = yf.download(ticker, start=start_date, end=end_date)
34
  return data
35
 
 
53
  return avg_diff if avg_diff < 0 else 0.0
54
 
55
 
 
 
 
 
 
 
 
56
  def score_today_candle(data, window=4):
57
  """Score today's candle based on the downtrend from the past 'window' days."""
58
  if len(data) < window + 1:
 
63
 
64
  close_price = today_candle['Close']
65
  previous_data = data.iloc[-(window+1):-1]
66
+
67
  down_High = average_downtrend(previous_data, method="High", window=window) + average_downtrend(previous_data, method="High", window=7) / 2
68
  down_Close = average_downtrend(previous_data, method="Close", window=window) + average_downtrend(previous_data, method="Close", window=7) / 2
69
  avg_downtrend = (down_High + down_Close) / 2
 
76
  sma_20 = calculate_sma(data, window=20).iloc[-1]
77
  ema_10 = calculate_ema(data, window=10).iloc[-1]
78
 
79
+ if (close_price < ema_10) or (close_price < sma_20) or (close_price < sma_50) or (close_price < sma_200):
80
  return -1
81
+
82
  return score_candle(today_candle, prev_candle, abs(avg_downtrend))
83
 
84
 
 
 
 
 
 
 
 
 
 
 
85
  def scan_sp500(top_n=25, progress=gr.Progress()):
86
  tickers = load_sp500_tickers()
87
+ scores = []
88
  tickers.append("QQQ")
89
 
 
90
  with ThreadPoolExecutor(max_workers=10) as executor:
91
+ futures = {executor.submit(load_data, ticker): ticker for ticker in tickers}
92
+ total_tickers = len(futures)
93
+
94
+ for i, future in enumerate(as_completed(futures)):
95
+ ticker = futures[future]
96
+ data = future.result()
97
+
98
+ if not data.empty:
99
+ score = score_today_candle(data)
100
+ if score > 0:
101
+ scores.append((ticker, score))
102
+
103
+ # Update progress after each ticker is processed
104
+ progress(i / total_tickers, desc=f"Processing {ticker}")
105
 
106
  scores = sorted(scores, key=lambda x: x[1], reverse=True)
107
  return scores[:top_n]
108
 
109
 
110
+ def next_business_day(date):
111
+ next_day = date + timedelta(days=1)
112
+ while next_day.weekday() >= 5: # 5 = Saturday, 6 = Sunday
113
+ next_day += timedelta(days=1)
114
+ return next_day
115
+
116
+
117
  def gradio_scan_sp500(top_n, progress=gr.Progress()):
118
+ progress(0, desc="Loading S&P 500 Tickers")
119
  tickers = load_sp500_tickers()
120
  tickers.append("QQQ")
121
 
122
+ progress(0.2, desc="Running Stock Scanning")
123
  results = scan_sp500(top_n, progress)
124
 
125
  last_data = load_data(results[0][0])
 
128
  date_created = next_market_day.strftime("%Y-%m-%d")
129
 
130
  output = f"Scan Results for Market Open on: {date_created}\n\n"
131
+ output += f"Top {top_n} stocks based on pattern finder score:\n\n"
132
  for ticker, score in results:
133
+ output += f"{ticker}: Total Score = {score:.2f}\n"
134
  return output
135
 
136
+
137
  iface = gr.Interface(
138
  fn=gradio_scan_sp500,
139
  inputs=gr.Slider(minimum=1, maximum=100, step=1, label="Number of top stocks to display", value=25),