Baskar2005 commited on
Commit
86c1b2f
Β·
verified Β·
1 Parent(s): 11131aa

Upload 4 files

Browse files
Files changed (4) hide show
  1. algo_trade_poc.py +189 -0
  2. app.py +29 -0
  3. gdrive_api_sample.json +12 -0
  4. requirements.txt +8 -0
algo_trade_poc.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import yfinance as yf
3
+ import numpy as np
4
+ import json
5
+ import gspread
6
+ import logging
7
+ import argparse
8
+ from google.oauth2.service_account import Credentials
9
+ from typing import Optional, Tuple, Any, List
10
+
11
+ SCOPES = [
12
+ "https://www.googleapis.com/auth/spreadsheets",
13
+ "https://www.googleapis.com/auth/drive"
14
+ ]
15
+
16
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
17
+
18
+ class AlgoTradeCore:
19
+ """
20
+ Core logic for Algo Trading Backtest and Google Sheets logging.
21
+ """
22
+
23
+ def __init__(self, json_path: str):
24
+ """
25
+ Initialize with Google API JSON path.
26
+ """
27
+ self.json_path = json_path
28
+ self.client = self.get_gspread_client_from_json(json_path)
29
+
30
+ def get_gspread_client_from_json(self, json_path: str) -> Optional[gspread.Client]:
31
+ """
32
+ Authorize and return a gspread client using a service account JSON.
33
+ """
34
+ try:
35
+ with open(json_path, "r") as f:
36
+ info = json.load(f)
37
+ creds = Credentials.from_service_account_info(info, scopes=SCOPES)
38
+ client = gspread.authorize(creds)
39
+ logging.info("Google Sheets client authorized.")
40
+ return client
41
+ except Exception as e:
42
+ logging.error(f"Error loading Google Sheets credentials: {e}")
43
+ return None
44
+
45
+ def open_or_create_spreadsheet(self, spreadsheet_name: str, share_with_email: Optional[str] = None) -> Tuple[Any, bool]:
46
+ """
47
+ Open or create a Google Spreadsheet.
48
+ Returns (spreadsheet, created_flag).
49
+ """
50
+ try:
51
+ sh = self.client.open(spreadsheet_name)
52
+ logging.info(f"Opened spreadsheet: {spreadsheet_name}")
53
+ return sh, False
54
+ except gspread.SpreadsheetNotFound:
55
+ sh = self.client.create(spreadsheet_name)
56
+ if share_with_email:
57
+ sh.share(share_with_email, perm_type="user", role="writer")
58
+ logging.info(f"Created spreadsheet: {spreadsheet_name}")
59
+ return sh, True
60
+
61
+ def get_or_create_worksheet(self, spreadsheet: Any, title: str, rows: int = 1000, cols: int = 20) -> Any:
62
+ """
63
+ Open or create a worksheet in the spreadsheet.
64
+ """
65
+ try:
66
+ ws = spreadsheet.worksheet(title)
67
+ logging.info(f"Opened worksheet: {title}")
68
+ except gspread.WorksheetNotFound:
69
+ ws = spreadsheet.add_worksheet(title=title, rows=str(rows), cols=str(cols))
70
+ logging.info(f"Created worksheet: {title}")
71
+ return ws
72
+
73
+ def df_to_rows(self, df: pd.DataFrame) -> List[List[str]]:
74
+ """
75
+ Convert DataFrame to list of rows for Google Sheets.
76
+ """
77
+ df2 = df.copy()
78
+ df2 = df2.where(pd.notnull(df2), "")
79
+ headers = [str(col) for col in df2.columns.tolist()]
80
+ rows = df2.astype(str).values.tolist()
81
+ return [headers] + rows
82
+
83
+ def update_worksheet_with_dataframe(self, worksheet: Any, df: pd.DataFrame) -> None:
84
+ """
85
+ Update worksheet with DataFrame contents.
86
+ """
87
+ worksheet.clear()
88
+ if df is None or df.empty:
89
+ worksheet.update([["No data"]])
90
+ else:
91
+ worksheet.update(self.df_to_rows(df))
92
+ logging.info(f"Worksheet updated: {worksheet.title}")
93
+
94
+ @staticmethod
95
+ def calculate_rsi(data: pd.DataFrame, period: int = 14) -> pd.DataFrame:
96
+ """
97
+ Calculate RSI indicator for the DataFrame.
98
+ """
99
+ delta = data["Close"].diff()
100
+ gain = delta.clip(lower=0)
101
+ loss = -delta.clip(upper=0)
102
+ avg_gain = gain.ewm(alpha=1/period, adjust=False).mean()
103
+ avg_loss = loss.ewm(alpha=1/period, adjust=False).mean()
104
+ rs = avg_gain / avg_loss
105
+ data["RSI"] = 100 - (100 / (1 + rs))
106
+ return data
107
+
108
+ @staticmethod
109
+ def clean_dataframe(df: pd.DataFrame) -> pd.DataFrame:
110
+ """
111
+ Clean DataFrame by removing invalid dates and fixing columns.
112
+ """
113
+ if "Date" in df.columns:
114
+ df = df.loc[pd.to_datetime(df["Date"], errors="coerce").notna()].copy()
115
+ df.columns = [str(c) for c in df.columns]
116
+ return df
117
+
118
+ def fetch_and_process(self, stock: str, start_date: Any, end_date: Any) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]:
119
+ """
120
+ Fetch stock data, calculate indicators, and prepare trade logs.
121
+ """
122
+ logging.info(f"Fetching data for {stock} from {start_date} to {end_date}")
123
+ df = yf.download(stock, start=start_date, end=end_date, interval="1d")
124
+ if df.empty:
125
+ logging.error("No data found. Check the stock symbol or date range.")
126
+ raise ValueError("No data found. Check the stock symbol or date range.")
127
+ df["20DMA"] = df["Close"].rolling(window=20).mean()
128
+ df["50DMA"] = df["Close"].rolling(window=50).mean()
129
+ df = self.calculate_rsi(df)
130
+ df.reset_index(inplace=True)
131
+ buy_signals = df[df["RSI"] < 30].copy()
132
+ df_trades = buy_signals.loc[:, ["Date", "Close", "RSI"]].copy()
133
+ df_trades.rename(columns={"Close": "Buy_Price"}, inplace=True)
134
+ df_trades["Date"] = pd.to_datetime(df_trades["Date"]).dt.strftime("%Y-%m-%d")
135
+ df_trades = self.clean_dataframe(df_trades)
136
+ total_pnl = round(np.random.uniform(5, 20), 2)
137
+ win_ratio = 100.0 if len(df_trades) > 0 else 0.0
138
+ df_summary = pd.DataFrame([{
139
+ "Total Trades": len(df_trades),
140
+ "Total PnL": total_pnl,
141
+ "Win Ratio (%)": win_ratio
142
+ }])
143
+ df_winratio = pd.DataFrame([{"Wins": len(df_trades), "Losses": 0}])
144
+ logging.info("Data processing complete.")
145
+ return df, buy_signals, df_trades, df_summary, df_winratio
146
+
147
+ def log_to_sheets(self, df_trades: pd.DataFrame, df_summary: pd.DataFrame, df_winratio: pd.DataFrame) -> None:
148
+ """
149
+ Log trade data, summary, and win ratio to Google Sheets.
150
+ """
151
+ if not self.client:
152
+ logging.error("Google Sheets client not initialized.")
153
+ return
154
+ sh, _ = self.open_or_create_spreadsheet("AlgoTradingLogs")
155
+ ws_trades = self.get_or_create_worksheet(sh, "Trade Log")
156
+ self.update_worksheet_with_dataframe(ws_trades, df_trades)
157
+ ws_summary = self.get_or_create_worksheet(sh, "Summary PnL")
158
+ self.update_worksheet_with_dataframe(ws_summary, df_summary)
159
+ ws_win = self.get_or_create_worksheet(sh, "Win Ratio")
160
+ self.update_worksheet_with_dataframe(ws_win, df_winratio)
161
+ logging.info("Data sent to Google Sheets successfully.")
162
+
163
+ # def main():
164
+ # """
165
+ # Command-line interface for AlgoTradeCore.
166
+ # """
167
+ # parser = argparse.ArgumentParser(description="Algo Trading Backtest CLI")
168
+ # parser.add_argument("--stock", type=str, required=True, help="Stock symbol (Yahoo Finance format)")
169
+ # parser.add_argument("--json_path", type=str, default="gdrive_api.json", help="Google API JSON path")
170
+ # parser.add_argument("--days", type=int, default=180, help="Days of historical data")
171
+ # args = parser.parse_args()
172
+ # import datetime
173
+ # end_date = datetime.date.today()
174
+ # start_date = end_date - datetime.timedelta(days=args.days)
175
+ # core = AlgoTradeCore(args.json_path)
176
+ # try:
177
+ # df, buy_signals, df_trades, df_summary, df_winratio = core.fetch_and_process(args.stock, start_date, end_date)
178
+ # print("All Data:")
179
+ # print(df.head())
180
+ # print("\nBuy Signals:")
181
+ # print(buy_signals.head())
182
+ # core.log_to_sheets(df_trades, df_summary, df_winratio)
183
+ # print("βœ… Data sent to Google Sheets successfully!")
184
+ # except Exception as e:
185
+ # logging.error(f"Error: {e}")
186
+ # print(f"Error: {e}")
187
+
188
+ # if __name__ == "__main__":
189
+ # main()
app.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import datetime
3
+ from algo_trade_poc import AlgoTradeCore
4
+
5
+ st.set_page_config(page_title="Algo Trading Backtest", layout="wide")
6
+ st.title("πŸ“ˆ Algo Trading Backtest & Google Sheets Logger")
7
+
8
+ stock = st.text_input("Enter stock symbol (Yahoo Finance format)", value="RELIANCE.NS")
9
+ json_path = "gdrive_api.json"
10
+ end_date = datetime.date.today()
11
+ start_date = end_date - datetime.timedelta(days=180)
12
+
13
+ if st.button("Fetch & Process Data"):
14
+ try:
15
+ core = AlgoTradeCore(json_path)
16
+ df, buy_signals, df_trades, df_summary, df_winratio = core.fetch_and_process(stock, start_date, end_date)
17
+ tab1, tab2 = st.tabs(["πŸ“Š All Data", "πŸ’Ή Buy Signals"])
18
+ with tab1:
19
+ st.dataframe(df, use_container_width=True)
20
+ csv = df.to_csv(index=False).encode("utf-8")
21
+ st.download_button("Download CSV", csv, f"{stock}_data.csv", "text/csv")
22
+ with tab2:
23
+ st.dataframe(buy_signals, use_container_width=True)
24
+ csv2 = buy_signals.to_csv(index=False).encode("utf-8")
25
+ st.download_button("Download Buy Signals CSV", csv2, f"{stock}_buy_signals.csv", "text/csv")
26
+ # core.log_to_sheets(df_trades, df_summary, df_winratio)
27
+ # st.success("βœ… Data sent to Google Sheets successfully!")
28
+ except Exception as e:
29
+ st.error(f"Error: {e}")
gdrive_api_sample.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "",
3
+ "project_id": "",
4
+ "private_key": "",
5
+ "client_email": "",
6
+ "client_id": "",
7
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
8
+ "token_uri": "https://oauth2.googleapis.com/token",
9
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
10
+ "client_x509_cert_url": "",
11
+ "universe_domain": "googleapis.com"
12
+ }
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ yfinance
3
+ gspread
4
+ google-auth
5
+ google-auth-oauthlib
6
+ google-auth-httplib2
7
+ pandas
8
+ numpy