Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -7,6 +7,7 @@ from datetime import datetime, time, timedelta
|
|
| 7 |
from pytz import timezone
|
| 8 |
import os
|
| 9 |
import csv
|
|
|
|
| 10 |
from streamlit_autorefresh import st_autorefresh
|
| 11 |
|
| 12 |
# --- Caching for SuperTrend calculation ---
|
|
@@ -38,6 +39,85 @@ def get_current_time():
|
|
| 38 |
"""Returns the current time in the 'Asia/Kolkata' timezone."""
|
| 39 |
return datetime.now(timezone("Asia/Kolkata"))
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
def clear_csv_data_without_header(file_path):
|
| 42 |
"""
|
| 43 |
Clears all data from a CSV file, leaving the header row intact.
|
|
@@ -1003,49 +1083,76 @@ if 'eod_positions_closed' not in st.session_state:
|
|
| 1003 |
st.sidebar.title("⚙️ Configuration")
|
| 1004 |
st.sidebar.success("Using hard-coded Indian market times (09:15 - 15:30).")
|
| 1005 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1006 |
st.sidebar.subheader("Signal Parameters")
|
| 1007 |
app_config = {
|
| 1008 |
-
'interval': st.sidebar.select_slider("Time Interval (minutes)", options=['1', '5', '15', '30', '60'], value='
|
| 1009 |
-
'limit': st.sidebar.slider("Scan Limit (stocks per signal)", 1, 10,
|
| 1010 |
-
'price_from': st.sidebar.number_input("Min Price", value=
|
| 1011 |
-
'price_to': st.sidebar.number_input("Max Price", value=
|
| 1012 |
-
'amount_per_trade': st.sidebar.number_input("Amount per Trade (₹)", value=
|
| 1013 |
-
'min_volume': st.sidebar.number_input("Minimum Volume", value=
|
| 1014 |
'market_start': time(9, 15),
|
| 1015 |
'market_end': time(15, 30),
|
| 1016 |
-
'clear_start': st.sidebar.time_input("Clear Start Time", value=
|
| 1017 |
-
'clear_end': st.sidebar.time_input("Clear End Time", value=
|
| 1018 |
}
|
| 1019 |
|
| 1020 |
# New setting for flexibility
|
| 1021 |
-
app_config['min_conditions'] = st.sidebar.select_slider("Minimum Conditions for Entry", options=[5, 4, 3, 2], value=
|
| 1022 |
|
| 1023 |
st.sidebar.subheader("Universal Exit Strategy")
|
| 1024 |
-
app_config['enable_profit_target'] = st.sidebar.checkbox("Enable Profit Target", value=
|
| 1025 |
-
app_config['profit_target'] = st.sidebar.number_input("Profit Target (%)", min_value=0.1, value=
|
| 1026 |
-
app_config['enable_atr_stop'] = st.sidebar.checkbox("Enable ATR Stop-Loss", value=
|
| 1027 |
-
app_config['atr_multiplier'] = st.sidebar.number_input("ATR Multiplier", min_value=0.5, value=
|
| 1028 |
-
app_config['enable_adx_exit'] = st.sidebar.checkbox("Enable ADX Trend Exit", value=
|
| 1029 |
-
app_config['adx_threshold'] = st.sidebar.slider("ADX Threshold", 10, 40,
|
| 1030 |
-
app_config['enable_timeout_exit'] = st.sidebar.checkbox("Enable Timeout Exit", value=
|
| 1031 |
-
app_config['timeout_minutes'] = st.sidebar.number_input("Timeout (minutes)", min_value=1, value=
|
| 1032 |
|
| 1033 |
st.sidebar.subheader("Long Technical Exit Strategy")
|
| 1034 |
-
app_config['enable_rsi_exit_long'] = st.sidebar.checkbox("Enable RSI Cross-Below 70 Exit (L)", value=
|
| 1035 |
-
app_config['enable_ema_exit_long'] = st.sidebar.checkbox("Enable EMA Cross Exit (L)", value=
|
| 1036 |
-
app_config['enable_supertrend_exit_long'] = st.sidebar.checkbox("Enable SuperTrend Exit (L)", value=
|
| 1037 |
-
app_config['enable_macd_exit_long'] = st.sidebar.checkbox("Enable MACD Cross Exit (L)", value=
|
| 1038 |
|
| 1039 |
st.sidebar.subheader("Short Technical Exit Strategy")
|
| 1040 |
-
app_config['enable_profit_target_short'] = st.sidebar.checkbox("Enable Profit Target (S)", value=
|
| 1041 |
-
app_config['profit_target_short'] = st.sidebar.number_input("Profit Target (S) %", min_value=0.1, value=
|
| 1042 |
-
app_config['enable_rsi_exit_short'] = st.sidebar.checkbox("Enable RSI Cross-Above 30 Exit (S)", value=
|
| 1043 |
-
app_config['enable_ema_exit_short'] = st.sidebar.checkbox("Enable EMA Cross Exit (S)", value=
|
| 1044 |
-
app_config['enable_supertrend_exit_short'] = st.sidebar.checkbox("Enable SuperTrend Exit (S)", value=
|
| 1045 |
-
app_config['enable_macd_exit_short'] = st.sidebar.checkbox("Enable MACD Cross Exit (S)", value=
|
| 1046 |
|
| 1047 |
st.sidebar.subheader("Balance Management")
|
| 1048 |
-
app_config['initial_balance'] = st.sidebar.number_input("Initial Balance (₹)", min_value=1000, value=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1049 |
|
| 1050 |
# Show current balance and investment in sidebar
|
| 1051 |
def display_balance():
|
|
|
|
| 7 |
from pytz import timezone
|
| 8 |
import os
|
| 9 |
import csv
|
| 10 |
+
import json
|
| 11 |
from streamlit_autorefresh import st_autorefresh
|
| 12 |
|
| 13 |
# --- Caching for SuperTrend calculation ---
|
|
|
|
| 39 |
"""Returns the current time in the 'Asia/Kolkata' timezone."""
|
| 40 |
return datetime.now(timezone("Asia/Kolkata"))
|
| 41 |
|
| 42 |
+
def save_settings(config, filename="settings.json"):
|
| 43 |
+
"""Save current settings to a JSON file."""
|
| 44 |
+
try:
|
| 45 |
+
# Convert time objects to string format for JSON serialization
|
| 46 |
+
config_to_save = config.copy()
|
| 47 |
+
if 'market_start' in config_to_save:
|
| 48 |
+
config_to_save['market_start'] = config_to_save['market_start'].strftime('%H:%M')
|
| 49 |
+
if 'market_end' in config_to_save:
|
| 50 |
+
config_to_save['market_end'] = config_to_save['market_end'].strftime('%H:%M')
|
| 51 |
+
if 'clear_start' in config_to_save:
|
| 52 |
+
config_to_save['clear_start'] = config_to_save['clear_start'].strftime('%H:%M')
|
| 53 |
+
if 'clear_end' in config_to_save:
|
| 54 |
+
config_to_save['clear_end'] = config_to_save['clear_end'].strftime('%H:%M')
|
| 55 |
+
|
| 56 |
+
with open(filename, 'w') as f:
|
| 57 |
+
json.dump(config_to_save, f, indent=2)
|
| 58 |
+
return True
|
| 59 |
+
except Exception as e:
|
| 60 |
+
st.error(f"Error saving settings: {e}")
|
| 61 |
+
return False
|
| 62 |
+
|
| 63 |
+
def load_settings(filename="settings.json"):
|
| 64 |
+
"""Load settings from a JSON file."""
|
| 65 |
+
try:
|
| 66 |
+
if os.path.exists(filename):
|
| 67 |
+
with open(filename, 'r') as f:
|
| 68 |
+
config = json.load(f)
|
| 69 |
+
|
| 70 |
+
# Convert string time formats back to time objects
|
| 71 |
+
if 'market_start' in config:
|
| 72 |
+
config['market_start'] = datetime.strptime(config['market_start'], '%H:%M').time()
|
| 73 |
+
if 'market_end' in config:
|
| 74 |
+
config['market_end'] = datetime.strptime(config['market_end'], '%H:%M').time()
|
| 75 |
+
if 'clear_start' in config:
|
| 76 |
+
config['clear_start'] = datetime.strptime(config['clear_start'], '%H:%M').time()
|
| 77 |
+
if 'clear_end' in config:
|
| 78 |
+
config['clear_end'] = datetime.strptime(config['clear_end'], '%H:%M').time()
|
| 79 |
+
|
| 80 |
+
return config
|
| 81 |
+
return None
|
| 82 |
+
except Exception as e:
|
| 83 |
+
st.error(f"Error loading settings: {e}")
|
| 84 |
+
return None
|
| 85 |
+
|
| 86 |
+
def get_default_settings():
|
| 87 |
+
"""Get default settings configuration."""
|
| 88 |
+
return {
|
| 89 |
+
'interval': '5',
|
| 90 |
+
'limit': 3,
|
| 91 |
+
'price_from': 100,
|
| 92 |
+
'price_to': 2000,
|
| 93 |
+
'amount_per_trade': 5000,
|
| 94 |
+
'min_volume': 500000,
|
| 95 |
+
'market_start': time(9, 15),
|
| 96 |
+
'market_end': time(15, 30),
|
| 97 |
+
'clear_start': time(9, 10),
|
| 98 |
+
'clear_end': time(9, 12),
|
| 99 |
+
'min_conditions': 3,
|
| 100 |
+
'enable_profit_target': True,
|
| 101 |
+
'profit_target': 5.0,
|
| 102 |
+
'enable_atr_stop': True,
|
| 103 |
+
'atr_multiplier': 2.0,
|
| 104 |
+
'enable_adx_exit': True,
|
| 105 |
+
'adx_threshold': 20,
|
| 106 |
+
'enable_timeout_exit': True,
|
| 107 |
+
'timeout_minutes': 10,
|
| 108 |
+
'enable_rsi_exit_long': True,
|
| 109 |
+
'enable_ema_exit_long': True,
|
| 110 |
+
'enable_supertrend_exit_long': True,
|
| 111 |
+
'enable_macd_exit_long': True,
|
| 112 |
+
'enable_profit_target_short': True,
|
| 113 |
+
'profit_target_short': 5.0,
|
| 114 |
+
'enable_rsi_exit_short': True,
|
| 115 |
+
'enable_ema_exit_short': True,
|
| 116 |
+
'enable_supertrend_exit_short': True,
|
| 117 |
+
'enable_macd_exit_short': True,
|
| 118 |
+
'initial_balance': 100000
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
def clear_csv_data_without_header(file_path):
|
| 122 |
"""
|
| 123 |
Clears all data from a CSV file, leaving the header row intact.
|
|
|
|
| 1083 |
st.sidebar.title("⚙️ Configuration")
|
| 1084 |
st.sidebar.success("Using hard-coded Indian market times (09:15 - 15:30).")
|
| 1085 |
|
| 1086 |
+
# Load saved settings or use defaults
|
| 1087 |
+
saved_settings = load_settings()
|
| 1088 |
+
default_settings = get_default_settings()
|
| 1089 |
+
|
| 1090 |
+
# Settings persistence buttons
|
| 1091 |
+
st.sidebar.subheader("💾 Settings Management")
|
| 1092 |
+
col1, col2, col3 = st.sidebar.columns(3)
|
| 1093 |
+
|
| 1094 |
+
if col2.button("📂 Load Settings"):
|
| 1095 |
+
if saved_settings:
|
| 1096 |
+
st.session_state.loaded_settings = saved_settings
|
| 1097 |
+
st.sidebar.success("Settings loaded! Refresh to apply.")
|
| 1098 |
+
else:
|
| 1099 |
+
st.sidebar.warning("No saved settings found.")
|
| 1100 |
+
|
| 1101 |
+
if col3.button("🔄 Reset to Defaults"):
|
| 1102 |
+
st.session_state.loaded_settings = default_settings
|
| 1103 |
+
st.sidebar.success("Reset to defaults! Refresh to apply.")
|
| 1104 |
+
|
| 1105 |
+
# Use loaded settings if available, otherwise use defaults
|
| 1106 |
+
settings_to_use = st.session_state.get('loaded_settings', saved_settings if saved_settings else default_settings)
|
| 1107 |
+
|
| 1108 |
st.sidebar.subheader("Signal Parameters")
|
| 1109 |
app_config = {
|
| 1110 |
+
'interval': st.sidebar.select_slider("Time Interval (minutes)", options=['1', '5', '15', '30', '60'], value=settings_to_use['interval']),
|
| 1111 |
+
'limit': st.sidebar.slider("Scan Limit (stocks per signal)", 1, 10, settings_to_use['limit']),
|
| 1112 |
+
'price_from': st.sidebar.number_input("Min Price", value=settings_to_use['price_from']),
|
| 1113 |
+
'price_to': st.sidebar.number_input("Max Price", value=settings_to_use['price_to']),
|
| 1114 |
+
'amount_per_trade': st.sidebar.number_input("Amount per Trade (₹)", value=settings_to_use['amount_per_trade']),
|
| 1115 |
+
'min_volume': st.sidebar.number_input("Minimum Volume", value=settings_to_use['min_volume']),
|
| 1116 |
'market_start': time(9, 15),
|
| 1117 |
'market_end': time(15, 30),
|
| 1118 |
+
'clear_start': st.sidebar.time_input("Clear Start Time", value=settings_to_use['clear_start']),
|
| 1119 |
+
'clear_end': st.sidebar.time_input("Clear End Time", value=settings_to_use['clear_end']),
|
| 1120 |
}
|
| 1121 |
|
| 1122 |
# New setting for flexibility
|
| 1123 |
+
app_config['min_conditions'] = st.sidebar.select_slider("Minimum Conditions for Entry", options=[5, 4, 3, 2], value=settings_to_use['min_conditions'], help="Choose how many indicators must agree for a trade. 5 is strictest, 2 is most flexible.")
|
| 1124 |
|
| 1125 |
st.sidebar.subheader("Universal Exit Strategy")
|
| 1126 |
+
app_config['enable_profit_target'] = st.sidebar.checkbox("Enable Profit Target", value=settings_to_use['enable_profit_target'])
|
| 1127 |
+
app_config['profit_target'] = st.sidebar.number_input("Profit Target (%)", min_value=0.1, value=settings_to_use['profit_target'], step=0.1)
|
| 1128 |
+
app_config['enable_atr_stop'] = st.sidebar.checkbox("Enable ATR Stop-Loss", value=settings_to_use['enable_atr_stop'])
|
| 1129 |
+
app_config['atr_multiplier'] = st.sidebar.number_input("ATR Multiplier", min_value=0.5, value=settings_to_use['atr_multiplier'], step=0.1)
|
| 1130 |
+
app_config['enable_adx_exit'] = st.sidebar.checkbox("Enable ADX Trend Exit", value=settings_to_use['enable_adx_exit'])
|
| 1131 |
+
app_config['adx_threshold'] = st.sidebar.slider("ADX Threshold", 10, 40, settings_to_use['adx_threshold'])
|
| 1132 |
+
app_config['enable_timeout_exit'] = st.sidebar.checkbox("Enable Timeout Exit", value=settings_to_use['enable_timeout_exit'])
|
| 1133 |
+
app_config['timeout_minutes'] = st.sidebar.number_input("Timeout (minutes)", min_value=1, value=settings_to_use['timeout_minutes'], step=1)
|
| 1134 |
|
| 1135 |
st.sidebar.subheader("Long Technical Exit Strategy")
|
| 1136 |
+
app_config['enable_rsi_exit_long'] = st.sidebar.checkbox("Enable RSI Cross-Below 70 Exit (L)", value=settings_to_use['enable_rsi_exit_long'])
|
| 1137 |
+
app_config['enable_ema_exit_long'] = st.sidebar.checkbox("Enable EMA Cross Exit (L)", value=settings_to_use['enable_ema_exit_long'])
|
| 1138 |
+
app_config['enable_supertrend_exit_long'] = st.sidebar.checkbox("Enable SuperTrend Exit (L)", value=settings_to_use['enable_supertrend_exit_long'])
|
| 1139 |
+
app_config['enable_macd_exit_long'] = st.sidebar.checkbox("Enable MACD Cross Exit (L)", value=settings_to_use['enable_macd_exit_long'])
|
| 1140 |
|
| 1141 |
st.sidebar.subheader("Short Technical Exit Strategy")
|
| 1142 |
+
app_config['enable_profit_target_short'] = st.sidebar.checkbox("Enable Profit Target (S)", value=settings_to_use['enable_profit_target_short'])
|
| 1143 |
+
app_config['profit_target_short'] = st.sidebar.number_input("Profit Target (S) %", min_value=0.1, value=settings_to_use['profit_target_short'], step=0.1)
|
| 1144 |
+
app_config['enable_rsi_exit_short'] = st.sidebar.checkbox("Enable RSI Cross-Above 30 Exit (S)", value=settings_to_use['enable_rsi_exit_short'])
|
| 1145 |
+
app_config['enable_ema_exit_short'] = st.sidebar.checkbox("Enable EMA Cross Exit (S)", value=settings_to_use['enable_ema_exit_short'])
|
| 1146 |
+
app_config['enable_supertrend_exit_short'] = st.sidebar.checkbox("Enable SuperTrend Exit (S)", value=settings_to_use['enable_supertrend_exit_short'])
|
| 1147 |
+
app_config['enable_macd_exit_short'] = st.sidebar.checkbox("Enable MACD Cross Exit (S)", value=settings_to_use['enable_macd_exit_short'])
|
| 1148 |
|
| 1149 |
st.sidebar.subheader("Balance Management")
|
| 1150 |
+
app_config['initial_balance'] = st.sidebar.number_input("Initial Balance (₹)", min_value=1000, value=settings_to_use['initial_balance'], step=1000)
|
| 1151 |
+
|
| 1152 |
+
# Save settings button (after all configuration is complete)
|
| 1153 |
+
if col1.button("💾 Save Settings"):
|
| 1154 |
+
if save_settings(app_config):
|
| 1155 |
+
st.sidebar.success("Settings saved successfully!")
|
| 1156 |
|
| 1157 |
# Show current balance and investment in sidebar
|
| 1158 |
def display_balance():
|