Invicto69 commited on
Commit
026493b
·
verified ·
1 Parent(s): 43a5833

Synced repo using 'sync_with_huggingface' Github Action

Browse files
Files changed (4) hide show
  1. page/complete_backtest.py +30 -9
  2. page/single_backtest.py +27 -24
  3. strategies.py +3 -2
  4. utils.py +14 -12
page/complete_backtest.py CHANGED
@@ -6,6 +6,14 @@ from utils import complete_test
6
  from os import cpu_count
7
 
8
  def complete_backtest():
 
 
 
 
 
 
 
 
9
  st.markdown(
10
  """
11
  # Algorithmic Trading Dashboard
@@ -15,7 +23,6 @@ def complete_backtest():
15
 
16
  st.info("Strategy runs on most of the Nifty50 stocks", icon="ℹ️")
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)
@@ -24,7 +31,8 @@ def complete_backtest():
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:
@@ -39,23 +47,36 @@ def complete_backtest():
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(f"Multiprocess (use {cpu_count()} CPUs)", 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:
@@ -64,7 +85,7 @@ def complete_backtest():
64
  ### :orange[Nifty50 stocks backtest result by using {strategy}]
65
  ⬇️ Select a row in index column to get detailed information of the respective stock run.
66
  """)
67
- cols = ['stock', 'Start', 'End', 'Return [%]', 'Equity Final [$]', 'Buy & Hold Return [%]', '# Trades', 'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]']
68
  df = st.dataframe(st.session_state.results, hide_index=True, column_order=cols, on_select="rerun", selection_mode="single-row")
69
  df.selection.rows = 1
70
  if df.selection.rows:
 
6
  from os import cpu_count
7
 
8
  def complete_backtest():
9
+ @st.cache_data
10
+ def load_data():
11
+ # Load data
12
+ limits = pd.read_csv('data/yahoo_limits.csv')
13
+ return limits
14
+
15
+ limits = load_data()
16
+
17
  st.markdown(
18
  """
19
  # Algorithmic Trading Dashboard
 
23
 
24
  st.info("Strategy runs on most of the Nifty50 stocks", icon="ℹ️")
25
 
 
26
  period_list = ['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']
27
 
28
  c1, c2 = st.columns(2)
 
31
  strategy = st.selectbox("Select Strategy", ['Order Block', 'Order Block with EMA', 'Structure trading'], index=2)
32
  with c2:
33
  # Swing High/Low window size
34
+ swing_hl = st.number_input("Swing High/Low Window Size", min_value=1, value=10,
35
+ help = "Minimum window size for finding swing highs and lows.")
36
 
37
  c1, c2 = st.columns(2)
38
  with c1:
 
47
 
48
  # EMA parameters if "Order Block with EMA" is selected
49
  if strategy == "Order Block with EMA":
50
+ c1, c2, c3 = st.columns([2, 2, 1.5])
51
  with c1:
52
+ ema1 = st.number_input("Fast EMA Length", min_value=1, value=9,
53
+ help = "Length of Fast moving Exponential Moving Average.")
54
  with c2:
55
+ ema2 = st.number_input("Slow EMA Length", min_value=1, value=21,
56
+ help = "Length of Slow moving Exponential Moving Average.")
57
  with c3:
58
  cross_close = st.checkbox("Close trade on EMA crossover", value=False)
59
  else:
60
  ema1, ema2, cross_close = None, None, None
61
 
62
+ with st.expander("Advanced options"):
63
+ c1, c2, c3 = st.columns([2, 2, 1])
64
+ with c1:
65
+ initial_cash = st.number_input("Initial Cash [₹]", min_value=10000, value=10000)
66
+ with c2:
67
+ commission = st.number_input("Commission [%]", value = 0, min_value=-10, max_value=10,
68
+ help="Commission is the commission ratio. E.g. if your broker's "
69
+ "commission is 1% of trade value, set commission to 1.")
70
+ with c3:
71
+ multiprocess = st.checkbox(f"Multiprocess (use {cpu_count()} CPUs)", value=True)
72
 
73
  # Button to run the analysis
74
  if st.button("Run"):
75
  start = time.time()
76
+ st.session_state.results = complete_test(strategy, period, interval, multiprocess,
77
+ swing_hl=swing_hl, ema1=ema1, ema2=ema2,
78
+ cross_close=cross_close, cash=initial_cash,
79
+ commission=commission/100)
80
  st.success(f"Analysis finished in {round(time.time()-start, 2)} seconds")
81
 
82
  if "results" in st.session_state:
 
85
  ### :orange[Nifty50 stocks backtest result by using {strategy}]
86
  ⬇️ Select a row in index column to get detailed information of the respective stock run.
87
  """)
88
+ cols = ['stock', 'Start', 'End', 'Return [%]', 'Equity Final []', 'Buy & Hold Return [%]', '# Trades', 'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]']
89
  df = st.dataframe(st.session_state.results, hide_index=True, column_order=cols, on_select="rerun", selection_mode="single-row")
90
  df.selection.rows = 1
91
  if df.selection.rows:
page/single_backtest.py CHANGED
@@ -1,30 +1,19 @@
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, run_strategy
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']
@@ -62,20 +51,32 @@ def algorithmic_trading_dashboard():
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
  else:
77
  ema1, ema2, cross_close = None, None, None
78
 
 
 
 
 
 
 
 
 
 
79
  # Button to run the analysis
80
  if st.button("Run"):
81
  # Fetch ticker data
@@ -96,7 +97,9 @@ def algorithmic_trading_dashboard():
96
  .update_layout(title=dict(text=ticker))
97
  )
98
 
99
- backtest_results = run_strategy(ticker, strategy, period, interval, swing_hl=swing_hl, ema1=ema1, ema2=ema2, cross_close=cross_close)
 
 
100
 
101
  color = "green" if backtest_results['Return [%]'].values[0] > 0 else "red"
102
 
@@ -105,7 +108,7 @@ def algorithmic_trading_dashboard():
105
  st.plotly_chart(signal_plot, width=1200)
106
 
107
  st.write(f'### :{color}[Backtest Results]')
108
- cols = ['stock', 'Start', 'End', 'Return [%]', 'Equity Final [$]', 'Buy & Hold Return [%]', '# Trades',
109
  'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]']
110
  st.dataframe(backtest_results, hide_index=True, column_order=cols)
111
 
 
1
  import pandas as pd
2
  import streamlit as st
 
 
 
 
3
  from streamlit.components import v1 as components
4
 
5
  from indicators import SMC
6
  from utils import fetch, run_strategy
7
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  def algorithmic_trading_dashboard():
9
+ @st.cache_data
10
+ def load_data():
11
+ # Load data
12
+ symbols = pd.read_csv('data/Ticker_List_NSE_India.csv')
13
+ limits = pd.read_csv('data/yahoo_limits.csv')
14
+ return symbols, limits
15
+
16
+ symbols, limits = load_data()
17
 
18
  # Dropdown options
19
  period_list = ['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']
 
51
 
52
  with c2:
53
  # Swing High/Low window size
54
+ swing_hl = st.number_input("Swing High/Low Window Size", min_value=1, value=10,
55
+ help = "Minimum window size for finding swing highs and lows.")
56
 
57
  # EMA parameters if "Order Block with EMA" is selected
58
  if strategy == "Order Block with EMA":
59
  c1, c2, c3 = st.columns(3)
60
  with c1:
61
+ ema1 = st.number_input("Fast EMA Length", min_value=1, value=9,
62
+ help = "Length of Fast moving Exponential Moving Average.")
63
  with c2:
64
+ ema2 = st.number_input("Slow EMA Length", min_value=1, value=21,
65
+ help = "Length of Slow moving Exponential Moving Average.")
66
  with c3:
67
  cross_close = st.checkbox("Close trade on EMA crossover", value=False)
68
  else:
69
  ema1, ema2, cross_close = None, None, None
70
 
71
+ with st.expander("Advanced options"):
72
+ c1, c2 = st.columns(2)
73
+ with c1:
74
+ initial_cash = st.number_input("Initial Cash [₹]", min_value=10000, value=10000)
75
+ with c2:
76
+ commission = st.number_input("Commission [%]", value = 0, min_value=-10, max_value=10,
77
+ help="Commission is the commission ratio. E.g. if your broker's "
78
+ "commission is 1% of trade value, set commission to 1.")
79
+
80
  # Button to run the analysis
81
  if st.button("Run"):
82
  # Fetch ticker data
 
97
  .update_layout(title=dict(text=ticker))
98
  )
99
 
100
+ backtest_results = run_strategy(ticker, strategy, period, interval,
101
+ swing_hl=swing_hl, ema1=ema1, ema2=ema2, cross_close=cross_close,
102
+ cash=initial_cash, commission=commission/100)
103
 
104
  color = "green" if backtest_results['Return [%]'].values[0] > 0 else "red"
105
 
 
108
  st.plotly_chart(signal_plot, width=1200)
109
 
110
  st.write(f'### :{color}[Backtest Results]')
111
+ cols = ['stock', 'Start', 'End', 'Return [%]', 'Equity Final []', 'Buy & Hold Return [%]', '# Trades',
112
  'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]']
113
  st.dataframe(backtest_results, hide_index=True, column_order=cols)
114
 
strategies.py CHANGED
@@ -41,6 +41,7 @@ class SMC_test(Strategy):
41
 
42
 
43
  class SMC_ema(SignalStrategy, TrailingStrategy):
 
44
  ema1 = 9
45
  ema2 = 21
46
  close_on_crossover = False
@@ -49,8 +50,8 @@ class SMC_ema(SignalStrategy, TrailingStrategy):
49
  super().init()
50
 
51
  # Setting smc buy and sell indicators.
52
- self.smc_b = self.I(self.smc_buy, self.data.df)
53
- self.smc_s = self.I(self.smc_sell, self.data.df)
54
 
55
  close = self.data.Close
56
 
 
41
 
42
 
43
  class SMC_ema(SignalStrategy, TrailingStrategy):
44
+ swing_window = 10
45
  ema1 = 9
46
  ema2 = 21
47
  close_on_crossover = False
 
50
  super().init()
51
 
52
  # Setting smc buy and sell indicators.
53
+ self.smc_b = self.I(self.smc_buy, data=self.data.df, swing_hl=self.swing_window)
54
+ self.smc_s = self.I(self.smc_sell, data=self.data.df, swing_hl=self.swing_window)
55
 
56
  close = self.data.Close
57
 
utils.py CHANGED
@@ -13,21 +13,21 @@ def fetch(symbol, period, interval):
13
  df.columns =df.columns.get_level_values(0)
14
  return df
15
 
16
- def smc_backtest(data, filename, swing_hl, **kwargs):
17
- bt = Backtest(data, SMC_test, **kwargs)
18
- results = bt.run(swing_window=swing_hl)
19
  bt.plot(filename=filename, open_browser=False)
20
  return results
21
 
22
- def smc_ema_backtest(data, filename, ema1, ema2, closecross, **kwargs):
23
- bt = Backtest(data, SMC_ema, **kwargs)
24
- results = bt.run(ema1=ema1, ema2=ema2, close_on_crossover=closecross)
25
  bt.plot(filename=filename, open_browser=False)
26
  return results
27
 
28
- def smc_structure_backtest(data, filename, swing_hl, **kwargs):
29
- bt = Backtest(data, SMCStructure, **kwargs)
30
- results = bt.run(swing_window=swing_hl)
31
  bt.plot(filename=filename, open_browser=False)
32
  return results
33
 
@@ -51,11 +51,11 @@ def run_strategy(ticker_symbol, strategy, period, interval, **kwargs):
51
  filename = f'{ticker_symbol}.html'
52
 
53
  if strategy == "Order Block":
54
- backtest_results = smc_backtest(data, filename, kwargs['swing_hl'])
55
  elif strategy == "Order Block with EMA":
56
- backtest_results = smc_ema_backtest(data, filename, kwargs['ema1'], kwargs['ema2'], kwargs['cross_close'])
57
  elif strategy == "Structure trading":
58
- backtest_results = smc_structure_backtest(data, filename, kwargs['swing_hl'])
59
  else:
60
  raise Exception('Strategy not found')
61
 
@@ -75,6 +75,8 @@ def run_strategy(ticker_symbol, strategy, period, interval, **kwargs):
75
  'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]', 'plot']
76
  backtest_results = backtest_results[cols]
77
 
 
 
78
  return backtest_results
79
 
80
  def complete_test(strategy: str, period: str, interval: str, multiprocess=True, **kwargs):
 
13
  df.columns =df.columns.get_level_values(0)
14
  return df
15
 
16
+ def smc_backtest(data, filename, **kwargs):
17
+ bt = Backtest(data, SMC_test, cash=kwargs['cash'], commission=kwargs['commission'])
18
+ results = bt.run(swing_window=kwargs['swing_hl'])
19
  bt.plot(filename=filename, open_browser=False)
20
  return results
21
 
22
+ def smc_ema_backtest(data, filename, **kwargs):
23
+ bt = Backtest(data, SMC_ema, cash=kwargs['cash'], commission=kwargs['commission'])
24
+ results = bt.run(swing_window=kwargs['swing_hl'], ema1=kwargs['ema1'], ema2=kwargs['ema2'], close_on_crossover=kwargs['cross_close'])
25
  bt.plot(filename=filename, open_browser=False)
26
  return results
27
 
28
+ def smc_structure_backtest(data, filename, **kwargs):
29
+ bt = Backtest(data, SMCStructure, cash=kwargs['cash'], commission=kwargs['commission'])
30
+ results = bt.run(swing_window=kwargs['swing_hl'])
31
  bt.plot(filename=filename, open_browser=False)
32
  return results
33
 
 
51
  filename = f'{ticker_symbol}.html'
52
 
53
  if strategy == "Order Block":
54
+ backtest_results = smc_backtest(data, filename, **kwargs)
55
  elif strategy == "Order Block with EMA":
56
+ backtest_results = smc_ema_backtest(data, filename, **kwargs)
57
  elif strategy == "Structure trading":
58
+ backtest_results = smc_structure_backtest(data, filename, **kwargs)
59
  else:
60
  raise Exception('Strategy not found')
61
 
 
75
  'Win Rate [%]', 'Best Trade [%]', 'Worst Trade [%]', 'Avg. Trade [%]', 'plot']
76
  backtest_results = backtest_results[cols]
77
 
78
+ backtest_results = backtest_results.rename(columns = {'Equity Final [$]': 'Equity Final [₹]'})
79
+
80
  return backtest_results
81
 
82
  def complete_test(strategy: str, period: str, interval: str, multiprocess=True, **kwargs):