Invicto69 commited on
Commit
c3fc9c2
·
verified ·
1 Parent(s): 3041696

Synced repo using 'sync_with_huggingface' Github Action

Browse files
Files changed (4) hide show
  1. app.py +10 -6
  2. page/complete_backtest.py +71 -0
  3. page/single_backtest.py +112 -0
  4. utils.py +54 -42
app.py CHANGED
@@ -1,11 +1,15 @@
1
  import streamlit as st
2
 
3
- st.set_page_config(page_title="Algorithmic Trading Dashboard", layout="wide", initial_sidebar_state="auto",
4
- menu_items=None, page_icon=":chart_with_upwards_trend:")
 
5
 
6
- dashboard = st.Page("pages/dashboard.py", title="Dashboard")
7
- complete_test = st.Page("pages/complete_backtest.py", title="Nifty50 Test")
8
 
9
- pg = st.navigation([dashboard, complete_test])
10
 
11
- pg.run()
 
 
 
 
1
  import streamlit as st
2
 
3
+ def app():
4
+ st.set_page_config(page_title="Algorithmic Trading Dashboard", layout="wide", initial_sidebar_state="auto",
5
+ menu_items=None, page_icon=":chart_with_upwards_trend:")
6
 
7
+ single_test = st.Page("page/single_backtest.py", title="Run Strategy")
8
+ complete_test = st.Page("page/complete_backtest.py", title="Evaluate Strategy")
9
 
10
+ pg = st.navigation({'Algorithmic Trading Dashboard':[single_test, complete_test]})
11
 
12
+ pg.run()
13
+
14
+ if __name__ == "__main__":
15
+ app()
page/complete_backtest.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ # sys.path.append(r"D:\code\algotrading\backtesting")
3
+
4
+ import streamlit as st
5
+ import pandas as pd
6
+ import time
7
+ from streamlit.components import v1 as components
8
+ from utils import complete_test
9
+
10
+ def complete_backtest():
11
+ st.markdown(
12
+ """
13
+ # Algorithmic Trading Dashboard
14
+ ## Evaluate Strategy
15
+ """
16
+ )
17
+
18
+ limits = pd.read_csv('data/yahoo_limits.csv')
19
+ period_list = ['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']
20
+
21
+ c1, c2 = st.columns(2)
22
+ with c1:
23
+ # Select strategy
24
+ strategy = st.selectbox("Select Strategy", ['Order Block', 'Order Block with EMA', 'Structure trading'], index=2)
25
+ with c2:
26
+ # Swing High/Low window size
27
+ swing_hl = st.number_input("Swing High/Low Window Size", min_value=1, value=10)
28
+
29
+ c1, c2 = st.columns(2)
30
+ with c1:
31
+ # Select interval
32
+ interval = st.selectbox("Select Interval", limits['interval'].tolist(), index=3)
33
+ with c2:
34
+ # Update period options based on interval
35
+ limit = limits[limits['interval'] == interval]['limit'].values[0]
36
+ idx = period_list.index(limit)
37
+ period_options = period_list[:idx + 1] + ['max']
38
+ period = st.selectbox("Select Period", period_options, index=3)
39
+
40
+ # EMA parameters if "Order Block with EMA" is selected
41
+ if strategy == "Order Block with EMA":
42
+ c1, c2, c3 = st.columns(3)
43
+ with c1:
44
+ ema1 = st.number_input("Fast EMA Length", min_value=1, value=9)
45
+ with c2:
46
+ ema2 = st.number_input("Slow EMA Length", min_value=1, value=21)
47
+ with c3:
48
+ cross_close = st.checkbox("Close trade on EMA crossover", value=False)
49
+ else:
50
+ ema1, ema2, cross_close = None, None, None
51
+
52
+ multiprocess = st.checkbox("Multiprocess", value=True)
53
+
54
+ # Button to run the analysis
55
+ if st.button("Run"):
56
+ start = time.time()
57
+ st.session_state.results = complete_test(strategy, period, interval, multiprocess, swing_hl=swing_hl, ema1=ema1, ema2=ema2, cross_close=cross_close)
58
+ # st.write(f"Analysis finished in {time.strftime("%Hh%Mm%Ss", time.gmtime(time.time()-start))}")
59
+ st.success(f"Analysis finished in {round(time.time()-start, 2)} seconds")
60
+
61
+ if "results" in st.session_state:
62
+ st.write("⬇️ Select a row in index column to get detailed information of the respective stock run.")
63
+ cols = ['stock', 'Start', 'End', 'Return [%]', 'Equity Final [$]', 'Buy & Hold Return [%]', '# Trades', 'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]']
64
+ df = st.dataframe(st.session_state.results, hide_index=True, column_order=cols, on_select="rerun", selection_mode="single-row")
65
+ df.selection.rows = 1
66
+ if df.selection.rows:
67
+ row = df.selection.rows
68
+ plot = st.session_state.results['plot'].values[row]
69
+ components.html(plot[0], height=1067)
70
+
71
+ complete_backtest()
page/single_backtest.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import streamlit as st
3
+ import os
4
+ import random
5
+ from bokeh.io import output_file, save
6
+ from bokeh.plotting import figure
7
+ from streamlit.components import v1 as components
8
+
9
+ from indicators import SMC
10
+ from utils import fetch, smc_plot_backtest, smc_ema_plot_backtest, smc_structure_plot_backtest
11
+
12
+ def use_file_for_bokeh(chart: figure, chart_height=1067):
13
+ # Function used to replace st.boken_chart, because streamlit doesn't support bokeh v3
14
+ file_name = f'bokeh_graph_{random.getrandbits(8)}.html'
15
+ output_file(file_name)
16
+ save(chart)
17
+ with open(file_name, 'r', encoding='utf-8') as f:
18
+ html = f.read()
19
+ os.remove(file_name)
20
+ components.html(html, height=chart_height)
21
+
22
+ st.bokeh_chart = use_file_for_bokeh
23
+
24
+ def algorithmic_trading_dashboard():
25
+ # Load data
26
+ symbols = pd.read_csv('data/Ticker_List_NSE_India.csv')
27
+ limits = pd.read_csv('data/yahoo_limits.csv')
28
+
29
+ # Dropdown options
30
+ period_list = ['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']
31
+
32
+ st.markdown(
33
+ """
34
+ # Algorithmic Trading Dashboard
35
+ ## Run Strategy
36
+ """
37
+ )
38
+
39
+ # Input fields on the main page
40
+
41
+ # Select stock
42
+ stock = st.selectbox("Select Company", symbols['NAME OF COMPANY'].unique(), index=None)
43
+
44
+ c1, c2 = st.columns(2)
45
+
46
+ with c1:
47
+ # Select interval
48
+ interval = st.selectbox("Select Interval", limits['interval'].tolist(), index=3)
49
+
50
+ with c2:
51
+ # Update period options based on interval
52
+ limit = limits[limits['interval'] == interval]['limit'].values[0]
53
+ idx = period_list.index(limit)
54
+ period_options = period_list[:idx + 1] + ['max']
55
+ period = st.selectbox("Select Period", period_options, index=3)
56
+
57
+ c1, c2 = st.columns(2)
58
+
59
+ with c1:
60
+ # Select strategy
61
+ strategy = st.selectbox("Select Strategy", ['Order Block', 'Order Block with EMA', 'Structure trading'], index=2)
62
+
63
+ with c2:
64
+ # Swing High/Low window size
65
+ swing_hl = st.number_input("Swing High/Low Window Size", min_value=1, value=10)
66
+
67
+ # EMA parameters if "Order Block with EMA" is selected
68
+ if strategy == "Order Block with EMA":
69
+ c1, c2, c3 = st.columns(3)
70
+ with c1:
71
+ ema1 = st.number_input("Fast EMA Length", min_value=1, value=9)
72
+ with c2:
73
+ ema2 = st.number_input("Slow EMA Length", min_value=1, value=21)
74
+ with c3:
75
+ cross_close = st.checkbox("Close trade on EMA crossover", value=False)
76
+
77
+ # Button to run the analysis
78
+ if st.button("Run"):
79
+ # Fetch ticker data
80
+ ticker = symbols[symbols['NAME OF COMPANY'] == stock]['YahooEquiv'].values[0]
81
+ data = fetch(ticker, period, interval)
82
+
83
+ # Generate signal plot based on strategy
84
+ if strategy == "Order Block" or strategy == "Order Block with EMA":
85
+ signal_plot = (
86
+ SMC(data=data, swing_hl_window_sz=swing_hl)
87
+ .plot(order_blocks=True, swing_hl=True, show=False)
88
+ .update_layout(title=dict(text=ticker))
89
+ )
90
+ else:
91
+ signal_plot = (
92
+ SMC(data=data, swing_hl_window_sz=swing_hl)
93
+ .plot(swing_hl_v2=True, structure=True, show=False)
94
+ .update_layout(title=dict(text=ticker))
95
+ )
96
+
97
+ # Generate backtest plot
98
+ if strategy == "Order Block":
99
+ backtest_plot = smc_plot_backtest(data, 'test.html', swing_hl)
100
+ elif strategy == "Order Block with EMA":
101
+ backtest_plot = smc_ema_plot_backtest(data, 'test.html', ema1, ema2, cross_close)
102
+ elif strategy == "Structure trading":
103
+ backtest_plot = smc_structure_plot_backtest(data, 'test.html', swing_hl)
104
+
105
+ # Display plots
106
+ st.write("### Signal Plot")
107
+ st.plotly_chart(signal_plot, width=1200)
108
+
109
+ st.write("### Backtesting Plot")
110
+ st.bokeh_chart(backtest_plot)
111
+
112
+ algorithmic_trading_dashboard()
utils.py CHANGED
@@ -2,7 +2,11 @@ import yfinance as yf
2
  from backtesting import Backtest
3
  import pandas as pd
4
  import random
 
5
 
 
 
 
6
  from strategies import SMC_test, SMC_ema, SMCStructure
7
 
8
  def fetch(symbol, period, interval):
@@ -25,24 +29,59 @@ def smc_structure_plot_backtest(data, filename, swing_hl, **kwargs):
25
  bt.run(swing_window=swing_hl)
26
  return bt.plot(filename=filename, open_browser=False)
27
 
28
- def smc_backtest(data, swing_hl, **kwargs):
29
  bt = Backtest(data, SMC_test, **kwargs)
30
  results = bt.run(swing_window=swing_hl)
31
- bt.plot(filename='bokeh_graph.html', open_browser=False)
32
  return results
33
 
34
- def smc_ema_backtest(data, ema1, ema2, closecross, **kwargs):
35
  bt = Backtest(data, SMC_ema, **kwargs)
36
  results = bt.run(ema1=ema1, ema2=ema2, close_on_crossover=closecross)
37
- bt.plot(filename='bokeh_graph.html', open_browser=False)
38
  return results
39
 
40
- def smc_structure_backtest(data, swing_hl, **kwargs):
41
  bt = Backtest(data, SMCStructure, **kwargs)
42
  results = bt.run(swing_window=swing_hl)
43
- bt.plot(filename='bokeh_graph.html', open_browser=False)
44
  return results
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  def random_test(strategy: str, period: str, interval: str, no_of_stocks: int = 5, **kwargs):
47
  nifty50 = pd.read_csv("data/ind_nifty50list.csv")
48
  ticker_list = pd.read_csv("data/Ticker_List_NSE_India.csv")
@@ -89,52 +128,25 @@ def random_test(strategy: str, period: str, interval: str, no_of_stocks: int = 5
89
 
90
  return df
91
 
92
- def complete_test(strategy: str, period: str, interval: str, **kwargs):
93
  nifty50 = pd.read_csv("data/ind_nifty50list.csv")
94
  ticker_list = pd.read_csv("data/Ticker_List_NSE_India.csv")
95
 
96
  # Merging nifty50 and ticker_list dataframes to get 'YahooEquiv' column.
97
  nifty50 = nifty50.merge(ticker_list, "inner", left_on=['Symbol'], right_on=['SYMBOL'])
98
 
99
- df = pd.DataFrame()
100
-
101
- for i in range(len(nifty50)):
102
- # for i in range(5):
 
103
 
104
- # Fetching ohlc of random ticker_symbol.
105
- ticker_symbol = nifty50['YahooEquiv'].values[i]
106
- data = fetch(ticker_symbol, period, interval)
107
-
108
- if strategy == "Order Block":
109
- backtest_results = smc_backtest(data, kwargs['swing_hl'])
110
- elif strategy == "Order Block with EMA":
111
- backtest_results = smc_ema_backtest(data, kwargs['ema1'], kwargs['ema2'], kwargs['cross_close'])
112
- elif strategy == "Structure trading":
113
- backtest_results = smc_structure_backtest(data, kwargs['swing_hl'])
114
- else:
115
- raise Exception('Strategy not found')
116
-
117
- with open("bokeh_graph.html", 'r', encoding='utf-8') as f:
118
- plot = f.read()
119
-
120
- # Converting pd.Series to pd.Dataframe
121
- backtest_results = backtest_results.to_frame().transpose()
122
-
123
- backtest_results['stock'] = ticker_symbol
124
- backtest_results['plot'] = plot
125
-
126
- # Reordering columns.
127
- # cols = df.columns.tolist()
128
- # cols = cols[-1:] + cols[:-1]
129
- cols = ['stock', 'Start', 'End', 'Return [%]', 'Equity Final [$]', 'Buy & Hold Return [%]', '# Trades', 'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]', 'plot']
130
- backtest_results = backtest_results[cols]
131
-
132
- df = pd.concat([df, backtest_results])
133
 
134
  df['plot'] = df['plot'].astype(str)
135
  df = df.sort_values(by=['Return [%]'], ascending=False)
136
 
137
- return df
138
 
139
 
140
  if __name__ == "__main__":
@@ -143,5 +155,5 @@ if __name__ == "__main__":
143
  # df = yf.download('RELIANCE.NS', period='1yr', interval='15m')
144
 
145
  rt = complete_test("Order Block", '1mo', '15m', swing_hl=20)
146
- rt.to_excel('test/all_testing_1.xlsx', index=False)
147
  print(rt)
 
2
  from backtesting import Backtest
3
  import pandas as pd
4
  import random
5
+ import os
6
 
7
+ from multiprocessing import Pool
8
+ from itertools import repeat
9
+ import time
10
  from strategies import SMC_test, SMC_ema, SMCStructure
11
 
12
  def fetch(symbol, period, interval):
 
29
  bt.run(swing_window=swing_hl)
30
  return bt.plot(filename=filename, open_browser=False)
31
 
32
+ def smc_backtest(data, filename, swing_hl, **kwargs):
33
  bt = Backtest(data, SMC_test, **kwargs)
34
  results = bt.run(swing_window=swing_hl)
35
+ bt.plot(filename=filename, open_browser=False)
36
  return results
37
 
38
+ def smc_ema_backtest(data, filename, ema1, ema2, closecross, **kwargs):
39
  bt = Backtest(data, SMC_ema, **kwargs)
40
  results = bt.run(ema1=ema1, ema2=ema2, close_on_crossover=closecross)
41
+ bt.plot(filename=filename, open_browser=False)
42
  return results
43
 
44
+ def smc_structure_backtest(data, filename, swing_hl, **kwargs):
45
  bt = Backtest(data, SMCStructure, **kwargs)
46
  results = bt.run(swing_window=swing_hl)
47
+ bt.plot(filename=filename, open_browser=False)
48
  return results
49
 
50
+ def run_strategy(ticker_symbol, strategy, period, interval, kwargs):
51
+ # Fetching ohlc of random ticker_symbol.
52
+ data = fetch(ticker_symbol, period, interval)
53
+
54
+ filename = f'{ticker_symbol}.html'
55
+
56
+ if strategy == "Order Block":
57
+ backtest_results = smc_backtest(data, filename, kwargs['swing_hl'])
58
+ elif strategy == "Order Block with EMA":
59
+ backtest_results = smc_ema_backtest(data, filename, kwargs['ema1'], kwargs['ema2'], kwargs['cross_close'])
60
+ elif strategy == "Structure trading":
61
+ backtest_results = smc_structure_backtest(data, filename, kwargs['swing_hl'])
62
+ else:
63
+ raise Exception('Strategy not found')
64
+
65
+ with open(filename, 'r', encoding='utf-8') as f:
66
+ plot = f.read()
67
+
68
+ os.remove(filename)
69
+
70
+ # Converting pd.Series to pd.Dataframe
71
+ backtest_results = backtest_results.to_frame().transpose()
72
+
73
+ backtest_results['stock'] = ticker_symbol
74
+ backtest_results['plot'] = plot
75
+
76
+ # Reordering columns.
77
+ # cols = df.columns.tolist()
78
+ # cols = cols[-1:] + cols[:-1]
79
+ cols = ['stock', 'Start', 'End', 'Return [%]', 'Equity Final [$]', 'Buy & Hold Return [%]', '# Trades',
80
+ 'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]', 'plot']
81
+ backtest_results = backtest_results[cols]
82
+
83
+ return backtest_results
84
+
85
  def random_test(strategy: str, period: str, interval: str, no_of_stocks: int = 5, **kwargs):
86
  nifty50 = pd.read_csv("data/ind_nifty50list.csv")
87
  ticker_list = pd.read_csv("data/Ticker_List_NSE_India.csv")
 
128
 
129
  return df
130
 
131
+ def complete_test(strategy: str, period: str, interval: str, multiprocess=True, **kwargs):
132
  nifty50 = pd.read_csv("data/ind_nifty50list.csv")
133
  ticker_list = pd.read_csv("data/Ticker_List_NSE_India.csv")
134
 
135
  # Merging nifty50 and ticker_list dataframes to get 'YahooEquiv' column.
136
  nifty50 = nifty50.merge(ticker_list, "inner", left_on=['Symbol'], right_on=['SYMBOL'])
137
 
138
+ if multiprocess:
139
+ with Pool() as p:
140
+ result = p.starmap(run_strategy, zip(nifty50['YahooEquiv'].values, repeat(strategy), repeat(period), repeat(interval), repeat(kwargs)))
141
+ else:
142
+ result = [run_strategy(nifty50['YahooEquiv'].values[i], strategy, period, interval, kwargs) for i in range(len(nifty50))]
143
 
144
+ df = pd.concat(result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
  df['plot'] = df['plot'].astype(str)
147
  df = df.sort_values(by=['Return [%]'], ascending=False)
148
 
149
+ return df.reset_index().drop(columns=['index'])
150
 
151
 
152
  if __name__ == "__main__":
 
155
  # df = yf.download('RELIANCE.NS', period='1yr', interval='15m')
156
 
157
  rt = complete_test("Order Block", '1mo', '15m', swing_hl=20)
158
+ rt.to_excel('test/all_testing_2.xlsx', index=False)
159
  print(rt)