multiaccount first draft

This commit is contained in:
David Brazda
2024-10-08 13:43:23 +02:00
parent 79a033a633
commit 30931f60d4
11 changed files with 3220 additions and 4297 deletions

File diff suppressed because one or more lines are too long

View File

@ -1691,7 +1691,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.10"
"version": "3.10.11"
}
},
"nbformat": 4,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,932 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from v2realbot.tools.loadbatch import load_batch\n",
"from v2realbot.utils.utils import zoneNY\n",
"import pandas as pd\n",
"import numpy as np\n",
"import vectorbtpro as vbt\n",
"from itables import init_notebook_mode, show\n",
"import datetime\n",
"from itertools import product\n",
"from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, DATA_DIR\n",
"\n",
"init_notebook_mode(all_interactive=True)\n",
"\n",
"vbt.settings.set_theme(\"dark\")\n",
"vbt.settings['plotting']['layout']['width'] = 1280\n",
"vbt.settings.plotting.auto_rangebreaks = True\n",
"# Set the option to display with pagination\n",
"pd.set_option('display.notebook_repr_html', True)\n",
"pd.set_option('display.max_rows', 10) # Number of rows per page\n",
"\n",
"# Define the market open and close times\n",
"market_open = datetime.time(9, 30)\n",
"market_close = datetime.time(16, 0)\n",
"entry_window_opens = 1\n",
"entry_window_closes = 370\n",
"\n",
"forced_exit_start = 380\n",
"forced_exit_end = 390\n",
"\n",
"#LOAD FROM PARQUET\n",
"#list all files is dir directory with parquet extension\n",
"dir = DATA_DIR + \"/notebooks/\"\n",
"import os\n",
"files = [f for f in os.listdir(dir) if f.endswith(\".parquet\")]\n",
"#print('\\n'.join(map(str, files)))\n",
"file_name = \"ohlcv_df-SPY-2024-01-01T09:30:00-2024-05-14T16:00:00.parquet\"\n",
"ohlcv_df = pd.read_parquet(dir+file_name,engine='pyarrow')\n",
"basic_data = vbt.Data.from_data(vbt.symbol_dict({\"SPY\": ohlcv_df}), tz_convert=zoneNY)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#parameters (primary y line, secondary y line, close)\n",
"def plot_2y_close(priminds, secinds, close):\n",
" fig = vbt.make_subplots(rows=1, cols=1, shared_xaxes=True, specs=[[{\"secondary_y\": True}]], vertical_spacing=0.02, subplot_titles=(\"MOM\", \"Price\" ))\n",
" close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False), trace_kwargs=dict(line=dict(color=\"blue\")))\n",
" for ind in priminds:\n",
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
" for ind in secinds:\n",
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))\n",
" return fig\n",
"\n",
"# close = basic_data.xloc[\"09:30\":\"10:00\"].close"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#PIPELINE - FOR - LOOP\n",
"\n",
"#indicator parameters\n",
"mom_timeperiod = list(range(2, 12))\n",
"\n",
"#uzavreni okna od 1 do 200\n",
"#entry_window_closes = list(range(2, 50, 3))\n",
"entry_window_closes = [5, 10, 30, 45]\n",
"#entry_window_closes = 30\n",
"#threshold entries parameters\n",
"#long\n",
"mom_th = np.round(np.arange(0.01, 0.5 + 0.02, 0.02),4).tolist()#-0.02\n",
"# short\n",
"#mom_th = np.round(np.arange(-0.01, -0.3 - 0.02, -0.02),4).tolist()#-0.02\n",
"roc_th = np.round(np.arange(-0.2, -0.8 - 0.05, -0.05),4).tolist()#-0.2\n",
"#print(mom_th, roc_th)\n",
"\n",
"#portfolio simulation parameters\n",
"sl_stop =np.round(np.arange(0.02/100, 0.7/100, 0.05/100),4).tolist()\n",
"tp_stop = np.round(np.arange(0.02/100, 0.7/100, 0.05/100),4).tolist()\n",
"\n",
"combs = list(product(mom_timeperiod, mom_th, roc_th, sl_stop, tp_stop))\n",
"\n",
"@vbt.parameterized(merge_func = \"concat\", random_subset = 2000, show_progress=True) \n",
"def test_strat(entry_window_closes=60,\n",
" mom_timeperiod=2,\n",
" mom_th=-0.04,\n",
" #roc_th=-0.2,\n",
" sl_stop=0.19/100,\n",
" tp_stop=0.19/100):\n",
" # mom_timeperiod=2\n",
" # mom_th=-0.06\n",
" # roc_th=-0.2\n",
" # sl_stop=0.04/100\n",
" # tp_stop=0.04/100\n",
"\n",
" momshort = vbt.indicator(\"talib:MOM\").run(basic_data.close, timeperiod=mom_timeperiod, short_name = \"slope_short\")\n",
" rocp = vbt.indicator(\"talib:ROC\").run(basic_data.close, short_name = \"rocp\")\n",
" #rate of change + momentum\n",
"\n",
" #momshort.plot rocp.real_crossed_below(roc_th) & \n",
" #short_signal = momshort.real_crossed_below(mom_th)\n",
" long_signal = momshort.real_crossed_above(mom_th)\n",
" # print(\"short signal\")\n",
" # print(short_signal.value_counts())\n",
"\n",
" #forced_exit = pd.Series(False, index=close.index)\n",
" forced_exit = basic_data.symbol_wrapper.fill(False)\n",
" #entry_window_open = pd.Series(False, index=close.index)\n",
" entry_window_open= basic_data.symbol_wrapper.fill(False)\n",
"\n",
" #print(entry_window_closes, \"entry window closes\")\n",
" # Calculate the time difference in minutes from market open for each timestamp\n",
" elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)\n",
"\n",
" entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n",
"\n",
" #print(entry_window_open.value_counts())\n",
"\n",
" forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n",
" #short_entries = (short_signal & entry_window_open)\n",
" #short_exits = forced_exit\n",
" entries = (long_signal & entry_window_open)\n",
" exits = forced_exit\n",
" #long_entries.info()\n",
" #number of trues and falses in long_entries\n",
" #print(short_exits.value_counts())\n",
" #print(short_entries.value_counts())\n",
"\n",
" #fig = plot_2y_close([],[momshort, rocp], close)\n",
" #short_signal.vbt.signals.plot_as_entries(close, fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
" #print(sl_stop)\n",
" #tsl_th=sl_stop, \n",
" #short_entries=short_entries, short_exits=short_exits,\n",
" pf = vbt.Portfolio.from_signals(close=basic_data.close, entries=entries, exits=exits, tsl_stop=sl_stop, tp_stop = tp_stop, fees=0.0167/100, freq=\"1s\", price=\"close\") #sl_stop=sl_stop, tp_stop = sl_stop,\n",
" \n",
" return pf.stats([\n",
" 'total_return',\n",
" 'max_dd', \n",
" 'total_trades', \n",
" 'win_rate', \n",
" 'expectancy'\n",
" ])\n",
"\n",
"pf_results = test_strat(vbt.Param(entry_window_closes),\n",
" vbt.Param(mom_timeperiod),\n",
" vbt.Param(mom_th),\n",
" #vbt.Param(roc_th)\n",
" vbt.Param(sl_stop),\n",
" vbt.Param(tp_stop, condition=\"tp_stop > sl_stop\"))\n",
"pf_results = pf_results.unstack(level=-1)\n",
"pf_results.sort_values(by=[\"Total Return [%]\", \"Max Drawdown [%]\"], ascending=[False, True])\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#pf_results.load(\"10tiscomb.pickle\")\n",
"#pf_results.info()\n",
"\n",
"vbt.save(pf_results, \"8tiscomb_tsl.pickle\")\n",
"\n",
"# pf_results = vbt.load(\"8tiscomb_tsl.pickle\")\n",
"# pf_results\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# parallel_coordinates method¶\n",
"\n",
"# attach_px_methods.<locals>.plot_func(\n",
"# *args,\n",
"# layout=None,\n",
"# **kwargs\n",
"# )\n",
"\n",
"# pf_results.vbt.px.parallel_coordinates() #ocdf\n",
"\n",
"res = pf_results.reset_index()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf_results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from sklearn.decomposition import PCA\n",
"from sklearn.preprocessing import StandardScaler\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# Assuming pf_results is your DataFrame\n",
"# Convert columns to numeric, assuming NaNs where conversion fails\n",
"metrics = ['Total Return [%]', 'Max Drawdown [%]', 'Total Trades']\n",
"for metric in metrics:\n",
" pf_results[metric] = pd.to_numeric(pf_results[metric], errors='coerce')\n",
"\n",
"# Handle missing values, for example filling with the median\n",
"pf_results['Max Drawdown [%]'].fillna(pf_results['Max Drawdown [%]'].median(), inplace=True)\n",
"\n",
"# Extract the metrics into a new DataFrame\n",
"data_for_pca = pf_results[metrics]\n",
"\n",
"# Standardize the data before applying PCA\n",
"scaler = StandardScaler()\n",
"data_scaled = scaler.fit_transform(data_for_pca)\n",
"\n",
"# Apply PCA\n",
"pca = PCA(n_components=2) # Adjust components as needed\n",
"principal_components = pca.fit_transform(data_scaled)\n",
"\n",
"# Create a DataFrame with the principal components\n",
"pca_results = pd.DataFrame(data=principal_components, columns=['PC1', 'PC2'])\n",
"\n",
"# Visualize the results\n",
"plt.figure(figsize=(8,6))\n",
"plt.scatter(pca_results['PC1'], pca_results['PC2'], alpha=0.5)\n",
"plt.xlabel('Principal Component 1')\n",
"plt.ylabel('Principal Component 2')\n",
"plt.title('PCA of Strategy Optimization Results')\n",
"plt.grid(True)\n",
"plt.savefig(\"ddd.png\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Check if there is any unnamed level and rename it\n",
"if None in df.index.names:\n",
" # Generate new names list replacing None with 'stat'\n",
" new_names = ['stat' if name is None else name for name in df.index.names]\n",
" df.index.set_names(new_names, inplace=True)\n",
"\n",
"rs= df\n",
"\n",
"rs.info()\n",
"\n",
"\n",
"# # Now, 'stat' is the name of the previously unnamed level\n",
"\n",
"# # Filter for 'Total Return' assuming it is a correct identifier in the 'stat' level\n",
"# total_return_series = df.xs('Total Return [%]', level='stat')\n",
"\n",
"# # Sort the Series to get the largest 'Total Return' values\n",
"# sorted_series = total_return_series.sort_values(ascending=False)\n",
"\n",
"# # Print the sorted filtered data\n",
"# sorted_series.head(20)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sorted_series.vbt.save()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#df.info()\n",
"total_return_series = df.xs('Total Return [%]')\n",
"sorted_series = total_return_series.sort_values(ascending=False)\n",
"\n",
"# Display the top N entries, e.g., top 5\n",
"sorted_series.head(5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"comb_stats_df.nlargest(10, 'Total Return [%]')\n",
"#stats_df.info()\n",
"\n",
"\n",
"8\t-0.06\t-0.2\t0.0028\t0.0048\t4.156254\n",
"4 -0.02 -0.25 0.0028 0.0048 0.84433\n",
"3 -0.02 -0.25 0.0033 0.0023 Total Return [%] 0.846753\n",
"#2\t-0.04\t-0.2\t0.0019\t0.0019\n",
"# 2\t-0.04\t-0.2\t0.0019\t0.0019\t0.556919\t91\t60.43956\t0.00612\n",
"# 2\t-0.04\t-0.25\t0.0019\t0.0019\t0.556919\t91\t60.43956\t0.00612\n",
"# 2\t-0.04\t-0.3\t0.0019\t0.0019\t0.556919\t91\t60.43956\t0.00612\n",
"# 2\t-0.04\t-0.35\t0.0019\t0.0019\t0.556919\t91\t60.43956\t0.00612\n",
"# 2\t-0.04\t-0.4\t0.0019\t0.0019\t0.556919\t91\t60.43956\t0.00612\n",
"# 2\t-0.04\t-0.2\t0.0019\t0.0017\t0.451338\t93\t63.44086\t0.004853\n",
"# 2\t-0.04\t-0.25\t0.0019\t0.0017\t0.451338\t93\t63.44086\t0.004853\n",
"# 2\t-0.04\t-0.3\t0.0019\t0.0017\t0.451338\t93\t63.44086\t0.004853\n",
"# 2\t-0.04\t-0.35\t0.0019\t0.0017\t0.451338\t93\t63.44086\t0.004853\n",
"# 2\t-0.04\t-0.4\t0.0019\t0.0017\t0.451338\t93\t63.44086\t0.004853"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf.plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"basic_data.symbols"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
">>> def apply_func(ts, entries, exits, fastw, sloww, minp=None):\n",
"... fast_ma = vbt.nb.rolling_mean_nb(ts, fastw, minp=minp)\n",
"... slow_ma = vbt.nb.rolling_mean_nb(ts, sloww, minp=minp)\n",
"... entries[:] = vbt.nb.crossed_above_nb(fast_ma, slow_ma) \n",
"... exits[:] = vbt.nb.crossed_above_nb(slow_ma, fast_ma)\n",
"... return (fast_ma, slow_ma) \n",
"\n",
">>> CrossSig = vbt.IF(\n",
"... class_name=\"CrossSig\",\n",
"... input_names=['ts'],\n",
"... in_output_names=['entries', 'exits'],\n",
"... param_names=['fastw', 'sloww'],\n",
"... output_names=['fast_ma', 'slow_ma']\n",
"... ).with_apply_func(\n",
"... apply_func,\n",
"... in_output_settings=dict(\n",
"... entries=dict(dtype=np.bool_), #initialize output with bool\n",
"... exits=dict(dtype=np.bool_)\n",
"... )\n",
"... )\n",
">>> cross_sig = CrossSig.run(ts2, 2, 4)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#PIPELINE - parameters in one go\n",
"\n",
"\n",
"#TOTO prepsat do FOR-LOOPu\n",
"\n",
"\n",
"#indicator parameters\n",
"mom_timeperiod = list(range(2, 6))\n",
"\n",
"#threshold entries parameters\n",
"mom_th = np.round(np.arange(-0.02, -0.1 - 0.02, -0.02),4).tolist()#-0.02\n",
"roc_th = np.round(np.arange(-0.2, -0.4 - 0.05, -0.05),4).tolist()#-0.2\n",
"#print(mom_th, roc_th)\n",
"#jejich product\n",
"# mom_th_prod, roc_th_prod = zip(*product(mom_th, roc_th))\n",
"\n",
"# #convert threshold to vbt param\n",
"# mom_th_index = vbt.Param(mom_th_prod, name='mom_th_th') \n",
"# roc_th_index = vbt.Param(roc_th_prod, name='roc_th_th')\n",
"\n",
"mom_th = vbt.Param(mom_th, name='mom_th')\n",
"roc_th = vbt.Param(roc_th, name='roc_th')\n",
"\n",
"#portfolio simulation parameters\n",
"sl_stop = np.arange(0.03/100, 0.2/100, 0.02/100).tolist()\n",
"# Using the round function\n",
"sl_stop = [round(val, 4) for val in sl_stop]\n",
"tp_stop = np.arange(0.03/100, 0.2/100, 0.02/100).tolist()\n",
"# Using the round function\n",
"tp_stop = [round(val, 4) for val in tp_stop]\n",
"sl_stop = vbt.Param(sl_stop) #np.nan mean s no stoploss\n",
"tp_stop = vbt.Param(tp_stop) #np.nan mean s no stoploss\n",
"\n",
"\n",
"#def test_mom(window=14, mom_th=0.2, roc_th=0.2, sl_stop=0.03/100, tp_stop=0.03/100):\n",
"#close = basic_data.xloc[\"09:30\":\"10:00\"].close\n",
"momshort = vbt.indicator(\"talib:MOM\").run(basic_data.get(\"Close\"), timeperiod=mom_timeperiod, short_name = \"slope_short\")\n",
"\n",
"#ht_trendline = vbt.indicator(\"talib:HT_TRENDLINE\").run(close, short_name = \"httrendline\")\n",
"rocp = vbt.indicator(\"talib:ROC\").run(basic_data.get(\"Close\"), short_name = \"rocp\")\n",
"#rate of change + momentum\n",
"\n",
"rocp_signal = rocp.real_crossed_below(mom_th)\n",
"mom_signal = momshort.real_crossed_below(roc_th)\n",
"\n",
"#mom_signal\n",
"print(rocp_signal.info())\n",
"print(mom_signal.info())\n",
"#print(rocp.real)\n",
"\n",
"\n",
"short_signal = (mom_signal.vbt & rocp_signal)\n",
"\n",
"# #short_signal = (rocp.real_crossed_below(roc_th_index) & momshort.real_crossed_below(mom_th_index))\n",
"# forced_exit = m1_data.symbol_wrapper.fill(False)\n",
"# entry_window_open= m1_data.symbol_wrapper.fill(False)\n",
"\n",
"\n",
"# # Calculate the time difference in minutes from market open for each timestamp\n",
"# elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)\n",
"\n",
"# entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n",
"# forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n",
"# short_entries = (short_signal & entry_window_open)\n",
"# short_exits = forced_exit\n",
"# #long_entries.info()\n",
"# #number of trues and falses in long_entries\n",
"# #short_exits.value_counts()\n",
"# #short_entries.value_counts()\n",
"\n",
"\n",
"# pf = vbt.Portfolio.from_signals(close=close, short_entries=short_entries, short_exits=short_exits, sl_stop=sl_stop, tp_stop = tp_stop, fees=0.0167/100, freq=\"1s\") #sl_stop=sl_stop, tp_stop = sl_stop,\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# filter dates"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#filter na dny\n",
"dates_of_interest = pd.to_datetime(['2024-04-22']).tz_localize('US/Eastern')\n",
"filtered_df = df.loc[df.index.normalize().isin(dates_of_interest)]\n",
"\n",
"df = filtered_df\n",
"df.info()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# import plotly.io as pio\n",
"# pio.renderers.default = 'notebook'\n",
"\n",
"#naloadujeme do vbt symbol as column\n",
"basic_data = vbt.Data.from_data({\"BAC\": df}, tz_convert=zoneNY)\n",
"\n",
"vbt.settings.plotting.auto_rangebreaks = True\n",
"#basic_data.data[\"BAC\"].vbt.ohlcv.plot()\n",
"\n",
"#basic_data.data[\"BAC\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m1_data = basic_data[['Open', 'High', 'Low', 'Close', 'Volume']]\n",
"\n",
"m1_data.data[\"BAC\"]\n",
"#m5_data = m1_data.resample(\"5T\")\n",
"\n",
"#m5_data.data[\"BAC\"].head(10)\n",
"\n",
"# m15_data = m1_data.resample(\"15T\")\n",
"\n",
"# m15 = m15_data.data[\"BAC\"]\n",
"\n",
"# m15.vbt.ohlcv.plot()\n",
"\n",
"# m1_data.wrapper.index\n",
"\n",
"# m1_resampler = m1_data.wrapper.get_resampler(\"1T\")\n",
"# m1_resampler.index_difference(reverse=True)\n",
"\n",
"\n",
"# m5_resampler.prettify()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# MOM indicator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vbt.phelp(vbt.indicator(\"talib:ROCP\").run)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"vyuzití rychleho klesani na sekundove urovni behem open rush\n",
"- MOM + ROC during open rush\n",
"- short signal\n",
"- pipeline kombinace thresholdu pro vstup mom_th, roc_th + hodnota sl_stop a tp_stop (pripadne trailing) - nalezeni optimalni kombinace atributu"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# fig = plot_2y_close([ht_trendline],[momshort, rocp], close)\n",
"# short_signal.vbt.signals.plot_as_entries(close, fig=fig, add_trace_kwargs=dict(secondary_y=False)) \n",
"\n",
"#parameters (primary y line, secondary y line, close)\n",
"def plot_2y_close(priminds, secinds, close):\n",
" fig = vbt.make_subplots(rows=1, cols=1, shared_xaxes=True, specs=[[{\"secondary_y\": True}]], vertical_spacing=0.02, subplot_titles=(\"MOM\", \"Price\" ))\n",
" close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False), trace_kwargs=dict(line=dict(color=\"blue\")))\n",
" for ind in priminds:\n",
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
" for ind in secinds:\n",
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))\n",
" return fig\n",
"\n",
"close = m1_data.xloc[\"09:30\":\"10:00\"].close\n",
"momshort = vbt.indicator(\"talib:MOM\").run(close, timeperiod=3, short_name = \"slope_short\")\n",
"ht_trendline = vbt.indicator(\"talib:HT_TRENDLINE\").run(close, short_name = \"httrendline\")\n",
"rocp = vbt.indicator(\"talib:ROC\").run(close, short_name = \"rocp\")\n",
"#rate of change + momentum\n",
"short_signal = (rocp.real_crossed_below(-0.2) & momshort.real_crossed_below(-0.02))\n",
"#indlong = vbt.indicator(\"talib:MOM\").run(close, timeperiod=10, short_name = \"slope_long\")\n",
"fig = plot_2y_close([ht_trendline],[momshort, rocp], close)\n",
"short_signal.vbt.signals.plot_as_entries(close, fig=fig, add_trace_kwargs=dict(secondary_y=False)) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"close = m1_data.close\n",
"#vbt.phelp(vbt.OLS.run)\n",
"\n",
"#oer steepmnes of regression line\n",
"#talib.LINEARREG_SLOPE(close, timeperiod=timeperiod)\n",
"#a také ON BALANCE VOLUME - http://5.161.179.223:8000/static/js/vbt/api/indicators/custom/obv/index.html\n",
"\n",
"\n",
"\n",
"mom_ind = vbt.indicator(\"talib:MOM\") \n",
"#vbt.phelp(mom_ind.run)\n",
"\n",
"mom = mom_ind.run(close, timeperiod=10)\n",
"\n",
"plot_2y_close(mom, close)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# defining ENTRY WINDOW and forced EXIT window"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#m1_data.data[\"BAC\"].info()\n",
"import datetime\n",
"# Define the market open and close times\n",
"market_open = datetime.time(9, 30)\n",
"market_close = datetime.time(16, 0)\n",
"entry_window_opens = 2\n",
"entry_window_closes = 30\n",
"\n",
"forced_exit_start = 380\n",
"forced_exit_end = 390\n",
"\n",
"forced_exit = m1_data.symbol_wrapper.fill(False)\n",
"entry_window_open= m1_data.symbol_wrapper.fill(False)\n",
"\n",
"# Calculate the time difference in minutes from market open for each timestamp\n",
"elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)\n",
"\n",
"entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n",
"forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n",
"\n",
"#entry_window_open.info()\n",
"# forced_exit.tail(100)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"close = m1_data.close\n",
"\n",
"#rsi = vbt.RSI.run(close, window=14)\n",
"\n",
"short_entries = (short_signal & entry_window_open)\n",
"short_exits = forced_exit\n",
"#long_entries.info()\n",
"#number of trues and falses in long_entries\n",
"#short_exits.value_counts()\n",
"short_entries.value_counts()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def plot_rsi(close, entries, exits):\n",
" fig = vbt.make_subplots(rows=1, cols=1, shared_xaxes=True, specs=[[{\"secondary_y\": True}]], vertical_spacing=0.02, subplot_titles=(\"RSI\", \"Price\" ))\n",
" close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))\n",
" #rsi.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
" entries.vbt.signals.plot_as_entries(close, fig=fig, add_trace_kwargs=dict(secondary_y=False)) \n",
" exits.vbt.signals.plot_as_exits(close, fig=fig, add_trace_kwargs=dict(secondary_y=False)) \n",
" return fig\n",
"\n",
"plot_rsi(close, short_entries, short_exits)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vbt.phelp(vbt.Portfolio.from_signals)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sl_stop = np.arange(0.03/100, 0.2/100, 0.02/100).tolist()\n",
"# Using the round function\n",
"sl_stop = [round(val, 4) for val in sl_stop]\n",
"print(sl_stop)\n",
"sl_stop = vbt.Param(sl_stop) #np.nan mean s no stoploss\n",
"\n",
"pf = vbt.Portfolio.from_signals(close=close, short_entries=short_entries, short_exits=short_exits, sl_stop=0.03/100, tp_stop = 0.03/100, fees=0.0167/100, freq=\"1s\") #sl_stop=sl_stop, tp_stop = sl_stop,\n",
"\n",
"#pf.stats()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#list of orders\n",
"#pf.orders.records_readable\n",
"#pf.orders.plots()\n",
"#pf.stats()\n",
"pf.stats()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf.plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf[(0.0015,0.0013)].plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf[0.03].plot_trade_signals()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# pristup k pf jako multi index"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#pf[0.03].plot()\n",
"#pf.order_records\n",
"pf[(0.03)].stats()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#zgrupovane statistiky\n",
"stats_df = pf.stats([\n",
" 'total_return',\n",
" 'total_trades',\n",
" 'win_rate',\n",
" 'expectancy'\n",
"], agg_func=None)\n",
"stats_df\n",
"\n",
"\n",
"stats_df.nlargest(10, 'Total Return [%]')\n",
"#stats_df.info()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf[(0.0011,0.0013000000000000002)].plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pandas.tseries.offsets import DateOffset\n",
"\n",
"temp_data = basic_data['2024-4-22']\n",
"temp_data\n",
"res1m = temp_data[[\"Open\", \"High\", \"Low\", \"Close\", \"Volume\"]]\n",
"\n",
"# Define a custom date offset that starts at 9:30 AM and spans 4 hours\n",
"custom_offset = DateOffset(hours=4, minutes=30)\n",
"\n",
"# res1m = res1m.get().resample(\"4H\").agg({ \n",
"# \"Open\": \"first\",\n",
"# \"High\": \"max\",\n",
"# \"Low\": \"min\",\n",
"# \"Close\": \"last\",\n",
"# \"Volume\": \"sum\"\n",
"# })\n",
"\n",
"res4h = res1m.resample(\"1h\", resample_kwargs=dict(origin=\"start\"))\n",
"\n",
"res4h.data\n",
"\n",
"res15m = res1m.resample(\"15T\", resample_kwargs=dict(origin=\"start\"))\n",
"\n",
"res15m.data[\"BAC\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"@vbt.njit\n",
"def long_entry_place_func_nb(c, low, close, time_in_ns, rsi14, window_open, window_close):\n",
" market_open_minutes = 570 # 9 hours * 60 minutes + 30 minutes\n",
"\n",
" for out_i in range(len(c.out)):\n",
" i = c.from_i + out_i\n",
"\n",
" current_minutes = vbt.dt_nb.hour_nb(time_in_ns[i]) * 60 + vbt.dt_nb.minute_nb(time_in_ns[i])\n",
" #print(\"current_minutes\", current_minutes)\n",
" # Calculate elapsed minutes since market open at 9:30 AM\n",
" elapsed_from_open = current_minutes - market_open_minutes\n",
" elapsed_from_open = elapsed_from_open if elapsed_from_open >= 0 else 0\n",
" #print( \"elapsed_from_open\", elapsed_from_open)\n",
"\n",
" #elapsed_from_open = elapsed_minutes_from_open_nb(time_in_ns) \n",
" in_window = elapsed_from_open > window_open and elapsed_from_open < window_close\n",
" #print(\"in_window\", in_window)\n",
" # if in_window:\n",
" # print(\"in window\")\n",
"\n",
" if in_window and rsi14[i] > 60: # and low[i, c.col] <= hit_price: # and hour == 9: # (4)!\n",
" return out_i\n",
" return -1\n",
"\n",
"@vbt.njit\n",
"def long_exit_place_func_nb(c, high, close, time_index, tp, sl): # (5)!\n",
" entry_i = c.from_i - c.wait\n",
" entry_price = close[entry_i, c.col]\n",
" hit_price = entry_price * (1 + tp)\n",
" stop_price = entry_price * (1 - sl)\n",
" for out_i in range(len(c.out)):\n",
" i = c.from_i + out_i\n",
" last_bar_of_day = vbt.dt_nb.day_changed_nb(time_index[i], time_index[i + 1])\n",
"\n",
" #print(next_day)\n",
" if last_bar_of_day: #pokud je dalsi next day, tak zavirame posledni\n",
" print(\"ted\",out_i)\n",
" return out_i\n",
" if close[i, c.col] >= hit_price or close[i, c.col] <= stop_price :\n",
" return out_i\n",
" return -1\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.DataFrame(np.random.random(size=(5, 10)), columns=list('abcdefghij'))\n",
"\n",
"df"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.sum()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,782 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# SUPERTREND\n",
"\n",
"* kombinace supertrendu na vice urovnich"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"from dotenv import load_dotenv\n",
"\n",
"#as V2realbot is client , load env variables here\n",
"env_file = \"/Users/davidbrazda/Documents/Development/python/.env\"\n",
"# Load the .env file\n",
"load_dotenv(env_file)\n",
"\n",
"from v2realbot.utils.utils import zoneNY\n",
"import pandas as pd\n",
"import numpy as np\n",
"import vectorbtpro as vbt\n",
"# from itables import init_notebook_mode, show\n",
"import datetime\n",
"from itertools import product\n",
"from v2realbot.config import DATA_DIR\n",
"from lightweight_charts import JupyterChart, chart, Panel, PlotAccessor\n",
"from IPython.display import display\n",
"\n",
"# init_notebook_mode(all_interactive=True)\n",
"\n",
"vbt.settings.set_theme(\"dark\")\n",
"vbt.settings['plotting']['layout']['width'] = 1280\n",
"vbt.settings.plotting.auto_rangebreaks = True\n",
"# Set the option to display with pagination\n",
"pd.set_option('display.notebook_repr_html', True)\n",
"pd.set_option('display.max_rows', 10) # Number of rows per page"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"trades_df-BAC-2024-01-01T09_30_00-2024-05-14T16_00_00-CO4B7VPWUZF-100.parquet\n",
"trades_df-BAC-2024-01-11T09:30:00-2024-01-12T16:00:00.parquet\n",
"trades_df-SPY-2024-01-01T09:30:00-2024-05-14T16:00:00.parquet\n",
"trades_df-BAC-2023-01-01T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n",
"ohlcv_df-BAC-2024-01-11T09:30:00-2024-01-12T16:00:00.parquet\n",
"trades_df-BAC-2024-05-15T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n",
"ohlcv_df-BAC-2024-01-01T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n",
"ohlcv_df-SPY-2024-01-01T09:30:00-2024-05-14T16:00:00.parquet\n",
"ohlcv_df-BAC-2024-01-01T09_30_00-2024-05-14T16_00_00-CO4B7VPWUZF-100.parquet\n",
"ohlcv_df-BAC-2023-01-01T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n",
"ohlcv_df-BAC-2023-01-01T09_30_00-2024-05-25T15_30_00-47BCFOPUVWZ-100.parquet\n"
]
},
{
"data": {
"text/plain": [
"351"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Define the market open and close times\n",
"market_open = datetime.time(9, 30)\n",
"market_close = datetime.time(16, 0)\n",
"entry_window_opens = 1\n",
"entry_window_closes = 370\n",
"forced_exit_start = 380\n",
"forced_exit_end = 390\n",
"\n",
"#LOAD FROM PARQUET\n",
"#list all files is dir directory with parquet extension\n",
"dir = DATA_DIR + \"/notebooks/\"\n",
"import os\n",
"files = [f for f in os.listdir(dir) if f.endswith(\".parquet\")]\n",
"print('\\n'.join(map(str, files)))\n",
"file_name = \"ohlcv_df-BAC-2023-01-01T09_30_00-2024-05-25T15_30_00-47BCFOPUVWZ-100.parquet\"\n",
"ohlcv_df = pd.read_parquet(dir+file_name,engine='pyarrow')\n",
"#filter ohlcv_df to certain date range (assuming datetime index)\n",
"#ohlcv_df = ohlcv_df.loc[\"2024-02-12 9:30\":\"2024-02-14 16:00\"]\n",
"\n",
"#add vwap column to ohlcv_df\n",
"#ohlcv_df[\"hlcc4\"] = (ohlcv_df[\"close\"] + ohlcv_df[\"high\"] + ohlcv_df[\"low\"] + ohlcv_df[\"close\"]) / 4\n",
"\n",
"basic_data = vbt.Data.from_data(vbt.symbol_dict({\"BAC\": ohlcv_df}), tz_convert=zoneNY)\n",
"ohlcv_df= None\n",
"basic_data.wrapper.index.normalize().nunique()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"DatetimeIndex: 4549772 entries, 2023-01-03 09:30:01-05:00 to 2024-05-24 15:59:59-04:00\n",
"Data columns (total 10 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
" 0 open float64 \n",
" 1 high float64 \n",
" 2 low float64 \n",
" 3 close float64 \n",
" 4 volume float64 \n",
" 5 trades float64 \n",
" 6 updated datetime64[ns, US/Eastern]\n",
" 7 vwap float64 \n",
" 8 buyvolume float64 \n",
" 9 sellvolume float64 \n",
"dtypes: datetime64[ns, US/Eastern](1), float64(9)\n",
"memory usage: 381.8 MB\n"
]
}
],
"source": [
"basic_data.data[\"BAC\"].info()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add resample function to custom columns"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from vectorbtpro.utils.config import merge_dicts, Config, HybridConfig\n",
"from vectorbtpro import _typing as tp\n",
"from vectorbtpro.generic import nb as generic_nb\n",
"\n",
"_feature_config: tp.ClassVar[Config] = HybridConfig(\n",
" {\n",
" \"buyvolume\": dict(\n",
" resample_func=lambda self, obj, resampler: obj.vbt.resample_apply(\n",
" resampler,\n",
" generic_nb.sum_reduce_nb,\n",
" )\n",
" ),\n",
" \"sellvolume\": dict(\n",
" resample_func=lambda self, obj, resampler: obj.vbt.resample_apply(\n",
" resampler,\n",
" generic_nb.sum_reduce_nb,\n",
" )\n",
" ),\n",
" \"trades\": dict(\n",
" resample_func=lambda self, obj, resampler: obj.vbt.resample_apply(\n",
" resampler,\n",
" generic_nb.sum_reduce_nb,\n",
" )\n",
" )\n",
" }\n",
")\n",
"\n",
"basic_data._feature_config = _feature_config"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"s1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','trades','sellvolume']]\n",
"\n",
"s5data = s1data.resample(\"5s\")\n",
"s5data = s5data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
"\n",
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','trades','sellvolume']].resample(\"1T\")\n",
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
"# t1data.data[\"BAC\"].info()\n",
"\n",
"t30data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','trades','sellvolume']].resample(\"30T\")\n",
"t30data = t30data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
"# t30data.data[\"BAC\"].info()\n",
"\n",
"s1close = s1data.close\n",
"t1close = t1data.close\n",
"t30close = t30data.close\n",
"t30volume = t30data.volume\n",
"\n",
"#resample on specific index \n",
"resampler = vbt.Resampler(t30data.index, s1data.index, source_freq=\"30T\", target_freq=\"1s\")\n",
"t30close_realigned = t30close.vbt.realign_closing(resampler)\n",
"\n",
"#resample 1min to s\n",
"resampler_s = vbt.Resampler(t1data.index, s1data.index, source_freq=\"1T\", target_freq=\"1s\")\n",
"t1close_realigned = t1close.vbt.realign_closing(resampler_s)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"datetime64[ns, US/Eastern]\n",
"datetime64[ns, US/Eastern]\n"
]
}
],
"source": [
"print(t30data.index.dtype)\n",
"print(s1data.index.dtype)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"DatetimeIndex: 4551 entries, 2023-01-03 09:30:00-05:00 to 2024-05-24 15:30:00-04:00\n",
"Data columns (total 9 columns):\n",
" # Column Non-Null Count Dtype \n",
"--- ------ -------------- ----- \n",
" 0 open 4551 non-null float64\n",
" 1 high 4551 non-null float64\n",
" 2 low 4551 non-null float64\n",
" 3 close 4551 non-null float64\n",
" 4 volume 4551 non-null float64\n",
" 5 vwap 4551 non-null float64\n",
" 6 buyvolume 4551 non-null float64\n",
" 7 trades 4551 non-null float64\n",
" 8 sellvolume 4551 non-null float64\n",
"dtypes: float64(9)\n",
"memory usage: 355.5 KB\n"
]
}
],
"source": [
"t30data.data[\"BAC\"].info()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vbt.IF.list_indicators(\"*vwap\")\n",
"vbt.phelp(vbt.VWAP.run)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# VWAP"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"t1vwap_h = vbt.VWAP.run(t1data.high, t1data.low, t1data.close, t1data.volume, anchor=\"H\")\n",
"t1vwap_d = vbt.VWAP.run(t1data.high, t1data.low, t1data.close, t1data.volume, anchor=\"D\")\n",
"t1vwap_t = vbt.VWAP.run(t1data.high, t1data.low, t1data.close, t1data.volume, anchor=\"T\")\n",
"\n",
"t1vwap_h_real = t1vwap_h.vwap.vbt.realign_closing(resampler_s)\n",
"t1vwap_d_real = t1vwap_d.vwap.vbt.realign_closing(resampler_s)\n",
"t1vwap_t_real = t1vwap_t.vwap.vbt.realign_closing(resampler_s)\n",
"\n",
"#t1vwap_5t.xloc[\"2024-01-3 09:30:00\":\"2024-01-03 16:00:00\"].plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#m30data.close.lw.plot()\n",
"#quick few liner\n",
"pane1 = Panel(\n",
" histogram=[\n",
" #(s1data.volume, \"volume\",None, 0.8),\n",
" #(m30volume, \"m30volume\",None, 1)\n",
" ], # [(series, name, \"rgba(53, 94, 59, 0.6)\", opacity)]\n",
" right=[\n",
" (s1data.close, \"1s close\"),\n",
" (t1data.close, \"1min close\"),\n",
" (t1vwap_t, \"1mvwap_t\"),\n",
" (t1vwap_h, \"1mvwap_h\"),\n",
" (t1vwap_d, \"1mvwap_d\"),\n",
" (t1vwap_t_real, \"1mvwap_t_real\"),\n",
" (t1vwap_h_real, \"1mvwap_h_real\"),\n",
" (t1vwap_d_real, \"1mvwap_d_real\")\n",
" # (t1close_realigned, \"1min close realigned\"),\n",
" # (m30data.close, \"30min-close\"),\n",
" # (m30close_realigned, \"30min close realigned\"),\n",
" ],\n",
")\n",
"ch = chart([pane1], size=\"s\", xloc=slice(\"2024-05-1 09:30:00\",\"2024-05-25 16:00:00\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# SUPERTREND"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"supertrend_s1 = vbt.SUPERTREND.run(s1data.high, s1data.low, s1data.close, period=5, multiplier=3)\n",
"direction_series_s1 = supertrend_s1.direction\n",
"supertrend_t1 = vbt.SUPERTREND.run(t1data.high, t1data.low, t1data.close, period=14, multiplier=3)\n",
"direction_series_t1 = supertrend_t1.direction\n",
"supertrend_t30 = vbt.SUPERTREND.run(t30data.high, t30data.low, t30data.close, period=14, multiplier=3)\n",
"direction_series_t30 = supertrend_t30.direction\n",
"\n",
"resampler_1t_sec = vbt.Resampler(direction_series_t1.index, direction_series_s1.index, source_freq=\"1T\", target_freq=\"1s\")\n",
"resampler_30t_sec = vbt.Resampler(direction_series_t30.index, direction_series_s1.index, source_freq=\"30T\", target_freq=\"1s\")\n",
"direction_series_t1_realigned = direction_series_t1.vbt.realign_closing(resampler_1t_sec)\n",
"direction_series_t30_realigned = direction_series_t30.vbt.realign_closing(resampler_30t_sec)\n",
"\n",
"#supertrend_s1.xloc[\"2024-01-3 09:30:00\":\"2024-01-03 16:00:00\"].plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# aligned_ups= pd.Series(False, index=direction_real.index)\n",
"# aligned_downs= pd.Series(False, index=direction_real.index)\n",
"\n",
"# aligned_ups = direction_real == 1 & supertrend.direction == 1\n",
"# aligned_ups"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"s5close = s5data.data[\"BAC\"].close\n",
"s5open = s5data.data[\"BAC\"].open\n",
"s5high = s5data.data[\"BAC\"].high\n",
"s5close_prev = s5close.shift(1)\n",
"s5open_prev = s5open.shift(1)\n",
"s5high_prev = s5high.shift(1)\n",
"#gap nahoru od byci svicky a nevraci se zpet na jeji uroven\n",
"entry_ups = (s5close_prev > s5open_prev) & (s5open > s5high_prev + 0.010) & (s5close > s5close_prev)\n",
"\n",
"entry_ups.value_counts()\n",
"\n",
"#entry_ups.info()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Entry window"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"market_open = datetime.time(9, 30)\n",
"market_close = datetime.time(16, 0)\n",
"entry_window_opens = 10\n",
"entry_window_closes = 370"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"entry_window_open= pd.Series(False, index=entry_ups.index)\n",
"# Calculate the time difference in minutes from market open for each timestamp\n",
"elapsed_min_from_open = (entry_ups.index.hour - market_open.hour) * 60 + (entry_ups.index.minute - market_open.minute)\n",
"entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n",
"#entry_window_open\n",
"\n",
"entry_ups = entry_ups & entry_window_open\n",
"# entry_ups\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"s5vwap_h = vbt.VWAP.run(s5data.high, s5data.low, s5data.close, s5data.volume, anchor=\"H\")\n",
"s5vwap_d = vbt.VWAP.run(s5data.high, s5data.low, s5data.close, s5data.volume, anchor=\"D\")\n",
"\n",
"# s5vwap_h_real = s5vwap_h.vwap.vbt.realign_closing(resampler_s)\n",
"# s5vwap_d_real = s5vwap_d.vwap.vbt.realign_closing(resampler_s)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pane1 = Panel(\n",
" ohlcv=(s5data.data[\"BAC\"],), #(series, entries, exits, other_markers)\n",
" histogram=[], # [(series, name, \"rgba(53, 94, 59, 0.6), opacity\")]\n",
" right=[#(bbands,), #[(series, name, entries, exits, other_markers)]\n",
" (s5data.data[\"BAC\"].close, \"close\", entry_ups),\n",
" (s5data.data[\"BAC\"].open, \"open\"),\n",
" (s5vwap_h, \"vwap5s_H\",),\n",
" (s5vwap_d, \"vwap5s_D\",)\n",
" # (t1data.data[\"BAC\"].vwap, \"vwap\"),\n",
" # (t1data.close, \"1min close\"),\n",
" # (supertrend_s1.trend,\"STtrend\"),\n",
" # (supertrend_s1.long,\"STlong\"),\n",
" # (supertrend_s1.short,\"STshort\")\n",
" ],\n",
" left = [\n",
" #(direction_series_s1,\"direction_s1\"),\n",
" # (direction_series_t1,\"direction_t1\"),\n",
" # (direction_series_t30,\"direction_t30\")\n",
" \n",
" ],\n",
" # right=[(bbands.upperband, \"upperband\",),\n",
" # (bbands.lowerband, \"lowerband\",),\n",
" # (bbands.middleband, \"middleband\",)\n",
" # ], #[(series, name, entries, exits, other_markers)]\n",
" middle1=[],\n",
" middle2=[],\n",
")\n",
"\n",
"# pane2 = Panel(\n",
"# ohlcv=(t1data.data[\"BAC\"],uptrend_m30, downtrend_m30), #(series, entries, exits, other_markers)\n",
"# histogram=[], # [(series, name, \"rgba(53, 94, 59, 0.6), opacity\")]\n",
"# left=[#(bbands,), #[(series, name, entries, exits, other_markers)]\n",
"# (direction_real,\"direction30min_real\"),\n",
"# ],\n",
"# # left = [(supertrendm30.direction,\"STdirection30\")],\n",
"# # # right=[(bbands.upperband, \"upperband\",),\n",
"# # # (bbands.lowerband, \"lowerband\",),\n",
"# # # (bbands.middleband, \"middleband\",)\n",
"# # # ], #[(series, name, entries, exits, other_markers)]\n",
"# middle1=[],\n",
"# middle2=[],\n",
"# title = \"1m\")\n",
"\n",
"ch = chart([pane1], sync=True, size=\"s\", xloc=slice(\"2024-02-20 09:30:00\",\"2024-02-22 16:00:00\"), precision=6)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# data = s5data.xloc[\"2024-01-03 09:30:00\":\"2024-03-10 16:00:00\"]\n",
"# entry = entry_ups.vbt.xloc[\"2024-01-03 09:30:00\":\"2024-03-10 16:00:00\"].obj\n",
"\n",
"pf = vbt.Portfolio.from_signals(close=s5data, entries=entry_ups, direction=\"longonly\", sl_stop=0.05/100, tp_stop = 0.05/100, fees=0.0167/100, freq=\"5s\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf.xloc[\"2024-01-26 09:30:00\":\"2024-02-28 16:00:00\"].positions.plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf.xloc[\"2024-01-26 09:30:00\":\"2024-01-28 16:00:00\"].plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pd.set_option('display.max_rows', None)\n",
"pf.stats()\n",
"# pf.xloc[\"monday\"].stats()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"buyvolume = t1data.data[\"BAC\"].buyvolume\n",
"sellvolume = t1data.data[\"BAC\"].sellvolume\n",
"totalvolume = buyvolume + sellvolume\n",
"\n",
"#adjust to minimal value to avoid division by zero\n",
"sellvolume_adjusted = sellvolume.replace(0, 1e-10)\n",
"oibratio = buyvolume / sellvolume\n",
"\n",
"#cumulative order flow (net difference)\n",
"cof = buyvolume - sellvolume\n",
"\n",
"# Calculate the order imbalance (net differene) normalize the order imbalance by calculating the difference between buy and sell volumes and then scaling it by the total volume.\n",
"order_imbalance = cof / totalvolume\n",
"order_imbalance = order_imbalance.fillna(0) #nan nahradime 0\n",
"\n",
"order_imbalance_allvolume = cof / t1data.data[\"BAC\"].volume\n",
"\n",
"order_imbalance_sma = vbt.indicator(\"talib:EMA\").run(order_imbalance, timeperiod=5)\n",
"short_signals = order_imbalance.vbt < -0.5\n",
"#short_entries = oibratio.vbt < 0.01\n",
"short_signals.value_counts()\n",
"short_signals.name = \"short_entries\"\n",
"#.fillna(False)\n",
"short_exits = short_signals.shift(-2).fillna(False).astype(bool)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pane1 = Panel(\n",
" ohlcv=(t1data.data[\"BAC\"],), #(series, entries, exits, other_markers)\n",
" histogram=[(order_imbalance_allvolume, \"oib_allvolume\", \"rgba(53, 94, 59, 0.6)\",0.5),\n",
" (t1data.data[\"BAC\"].trades, \"trades\",None,0.4),\n",
" ], # [(series, name, \"rgba(53, 94, 59, 0.6)\", opacity)]\n",
" # right=[\n",
" # (supertrend.trend,\"STtrend\"),\n",
" # (supertrend.long,\"STlong\"),\n",
" # (supertrend.short,\"STshort\")\n",
" # ],\n",
" # left = [(supertrend.direction,\"STdirection\")],\n",
" # right=[(bbands.upperband, \"upperband\",),\n",
" # (bbands.lowerband, \"lowerband\",),\n",
" # (bbands.middleband, \"middleband\",)\n",
" # ], #[(series, name, entries, exits, other_markers)]\n",
" middle1=[],\n",
" middle2=[],\n",
")\n",
"\n",
"pane2 = Panel(\n",
" ohlcv=(basic_data.data[\"BAC\"],), #(series, entries, exits, other_markers)\n",
" left=[(basic_data.data[\"BAC\"].trades, \"trades\")],\n",
" histogram=[(basic_data.data[\"BAC\"].trades, \"trades_hist\", \"white\", 0.5)], #\"rgba(53, 94, 59, 0.6)\"\n",
" # ], # [(series, name, \"rgba(53, 94, 59, 0.6)\")]\n",
" # right=[\n",
" # (supertrend.trend,\"STtrend\"),\n",
" # (supertrend.long,\"STlong\"),\n",
" # (supertrend.short,\"STshort\")\n",
" # ],\n",
" # left = [(supertrend.direction,\"STdirection\")],\n",
" # right=[(bbands.upperband, \"upperband\",),\n",
" # (bbands.lowerband, \"lowerband\",),\n",
" # (bbands.middleband, \"middleband\",)\n",
" # ], #[(series, name, entries, exits, other_markers)]\n",
" middle1=[],\n",
" middle2=[],\n",
")\n",
"\n",
"\n",
"ch = chart([pane1, pane2], size=\"m\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#short_signal = t1slope.real_below(t1_th) & t2slope.real_below(t2_th) & t3slope.real_below(t3_th) & t4slope.real_below(t4_th)\n",
"#long_signal = t1slope.real_above(t1_th) & t2slope.real_above(t2_th) & t3slope.real_above(t3_th) & t4slope.real_above(t4_th)\n",
"\n",
"#test na daily s reversem crossed 0\n",
"short_signal = t2slope.vbt < -0.01 & t3slope.vbt < -0.01 #min value of threshold\n",
"long_signal = t2slope.vbt > 0.01 & t3slope.vbt > 0.01 #min\n",
"\n",
"# thirty_up_signal = t3slope.vbt.crossed_above(0.01)\n",
"# thirty_down_signal = t3slope.vbt.crossed_below(-0.01)\n",
"\n",
"fig = plot_2y_close(priminds=[], secinds=[t3slope], close=t1data.close)\n",
"#short_signal.vbt.signals.plot_as_entries(basic_data.close, fig=fig)\n",
"\n",
"short_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"SHORTS\",\n",
" line=dict(color=\"#ffe476\"),\n",
" marker=dict(color=\"red\", symbol=\"triangle-down\"),\n",
" fill=None,\n",
" connectgaps=True,\n",
" ))\n",
"long_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"LONGS\",\n",
" line=dict(color=\"#ffe476\"),\n",
" marker=dict(color=\"limegreen\"),\n",
" fill=None,\n",
" connectgaps=True,\n",
" ))\n",
"\n",
"# thirty_down_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"DOWN30\",\n",
"# line=dict(color=\"#ffe476\"),\n",
"# marker=dict(color=\"yellow\", symbol=\"triangle-down\"),\n",
"# fill=None,\n",
"# connectgaps=True,\n",
"# ))\n",
"# thirty_up_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"UP30\",\n",
"# line=dict(color=\"#ffe476\"),\n",
"# marker=dict(color=\"grey\"),\n",
"# fill=None,\n",
"# connectgaps=True,\n",
"# ))\n",
"\n",
"# thirtymin_slope_to_compare.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True), trace_kwargs=dict(name=\"30min slope\",\n",
"# line=dict(color=\"yellow\"), \n",
"# fill=None,\n",
"# connectgaps=True,\n",
"# ))\n",
"\n",
"fig.show()\n",
"# print(\"short signal\")\n",
"# print(short_signal.value_counts())\n",
"\n",
"#forced_exit = pd.Series(False, index=close.index)\n",
"forced_exit = basic_data.symbol_wrapper.fill(False)\n",
"#entry_window_open = pd.Series(False, index=close.index)\n",
"entry_window_open= basic_data.symbol_wrapper.fill(False)\n",
"\n",
"# Calculate the time difference in minutes from market open for each timestamp\n",
"elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)\n",
"\n",
"entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n",
"\n",
"#print(entry_window_open.value_counts())\n",
"\n",
"forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n",
"short_entries = (short_signal & entry_window_open)\n",
"short_exits = forced_exit\n",
"\n",
"entries = (long_signal & entry_window_open)\n",
"exits = forced_exit\n",
"#long_entries.info()\n",
"#number of trues and falses in long_entries\n",
"# print(short_exits.value_counts())\n",
"# print(short_entries.value_counts())\n",
"\n",
"#fig = plot_2y_close([],[momshort, rocp], close)\n",
"#short_signal.vbt.signals.plot_as_entries(close, fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
"#print(sl_stop)\n",
"#short_entries=short_entries, short_exits=short_exits,\n",
"# pf = vbt.Portfolio.from_signals(close=basic_data, entries=short_entries, exits=exits, tsl_stop=0.005, tp_stop = 0.05, fees=0.0167/100, freq=\"1s\") #sl_stop=sl_stop, tp_stop = sl_stop,\n",
"\n",
"# pf.stats()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"forced_exit = t1data.symbol_wrapper.fill(False)\n",
"#entry_window_open = pd.Series(False, index=close.index)\n",
"entry_window_open= t1data.symbol_wrapper.fill(False)\n",
"\n",
"# Calculate the time difference in minutes from market open for each timestamp\n",
"elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)\n",
"\n",
"entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n",
"\n",
"#print(entry_window_open.value_counts())\n",
"\n",
"forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n",
"short_entries = (short_signals & entry_window_open)\n",
"short_exits = forced_exit\n",
"\n",
"entries = (long_signals & entry_window_open)\n",
"exits = forced_exit\n",
"\n",
"pf = vbt.Portfolio.from_signals(close=t1data, entries=entries, exits=exits, short_entries=short_entries, short_exits=exits,\n",
"td_stop=2, time_delta_format=\"rows\",\n",
"tsl_stop=0.005, tp_stop = 0.005, fees=0.0167/100)#, freq=\"1s\") #sl_stop=sl_stop, tp_stop = sl_stop,\n",
"\n",
"pf.stats()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf.plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf.get_drawdowns().records_readable"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pf.orders.records_readable"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

2
testy/testtt.py Normal file
View File

@ -0,0 +1,2 @@
import locale
print(locale.getdefaultlocale())

View File

@ -17,9 +17,6 @@ RUNNER_DETAIL_DIRECTORY = Path(__file__).parent.parent.parent / "runner_detail"
LOG_PATH = Path(__file__).parent.parent
LOG_FILE = Path(__file__).parent.parent / "strat.log"
JOB_LOG_FILE = Path(__file__).parent.parent / "job.log"
DOTENV_DIRECTORY = Path(__file__).parent.parent.parent
ENV_FILE = DOTENV_DIRECTORY / '.env'
#stratvars that cannot be changed in gui
STRATVARS_UNCHANGEABLES = ['pendingbuys', 'blockbuy', 'jevylozeno', 'limitka']
@ -30,6 +27,26 @@ MODEL_DIR = Path(DATA_DIR)/"models"
PROFILING_NEXT_ENABLED = False
PROFILING_OUTPUT_DIR = DATA_DIR
def find_dotenv(start_path):
"""
Searches for a .env file in the given directory or its parents and returns the path.
Args:
start_path: The directory to start searching from.
Returns:
Path to the .env file if found, otherwise None.
"""
current_path = Path(start_path)
for _ in range(6): # Limit search depth to 5 levels
dotenv_path = current_path / '.env'
if dotenv_path.exists():
return dotenv_path
current_path = current_path.parent
return None
ENV_FILE = find_dotenv(__file__)
#NALOADUJEME DOTENV ENV VARIABLES
if load_dotenv(ENV_FILE, verbose=True) is False:
print(f"Error loading.env file {ENV_FILE}. Now depending on ENV VARIABLES set externally.")

View File

@ -1,4 +1,4 @@
from threading import Thread
from threading import Thread, current_thread
from alpaca.trading.stream import TradingStream
from v2realbot.config import Keys
from v2realbot.common.model import Account
@ -41,6 +41,6 @@ class LiveOrderUpdatesStreamer(Thread):
print("connect strategy first")
return
self.client.subscribe_trade_updates(self.distributor)
print("*"*10, "WS Order Update Streamer started for", self.strategy.name, "*"*10)
print("*"*10, "WS Order Update Streamer started for", current_thread().name,"*"*10)
self.client.run()

View File

@ -150,9 +150,9 @@ class Strategy:
key = get_key(mode=mode, account=Account(account))
self.interface[account.name] = LiveInterface(symbol=self.symbol, key=key)
# order notif thread
self.order_notifs = LiveOrderUpdatesStreamer(key=key, name="WS-STRMR-" + account.name + "-" + self.name, account=account)
self.order_notifs[account.name] = LiveOrderUpdatesStreamer(key=key, name="WS-STRMR-" + account.name + "-" + self.name, account=account)
#propojujeme notifice s interfacem (pro callback)
self.order_notifs.connect_callback(self)
self.order_notifs[account.name].connect_callback(self)
self.state = StrategyState(name=self.name, accounts=self.accounts, account=self.account, symbol = self.symbol, stratvars = self.stratvars, interface=self.interface, rectype=self.rectype, runner_id=self.runner_id, ilog_save=self.ilog_save)

View File

@ -84,6 +84,7 @@ def execute_signal_generator(state: StrategyState, data, name):
state.ilog(lvl=1,e=f"{name} SHORT DISABLED")
if long_enabled is False:
state.ilog(lvl=1,e=f"{name} LONG DISABLED")
trade_made = None
#predkontroloa zda neni pending na accountu nebo aktivni trade
if state.account_variables[account_long].pending is None and state.account_variables[account_long].activeTrade is None and long_enabled and go_conditions_met(state, data,signalname=name, direction=TradeDirection.LONG):
multiplier = get_multiplier(state, data, options, TradeDirection.LONG)
@ -98,7 +99,9 @@ def execute_signal_generator(state: StrategyState, data, name):
direction=TradeDirection.LONG,
entry_price=None,
stoploss_value = None))
elif state.account_variables[account_short].pending is None and state.account_variables[account_short].activeTrade is None and short_enabled and go_conditions_met(state, data, signalname=name, direction=TradeDirection.SHORT):
trade_made = account_long
#pri multiaccountu muzeme udelat v jedne iteraci vice tradu avsak vzdy na ruznych accountech
if (trade_made is None or trade_made != account_short) and state.account_variables[account_short].pending is None and state.account_variables[account_short].activeTrade is None and short_enabled and go_conditions_met(state, data, signalname=name, direction=TradeDirection.SHORT):
multiplier = get_multiplier(state, data, options, TradeDirection.SHORT)
state.vars.prescribedTrades.append(Trade(
account=account_short,
@ -111,5 +114,5 @@ def execute_signal_generator(state: StrategyState, data, name):
direction=TradeDirection.SHORT,
entry_price=None,
stoploss_value = None))
else:
return
state.ilog(lvl=0,e=f"{name} NO SIGNAL")

255
venv1_packages.txt Normal file
View File

@ -0,0 +1,255 @@
absl-py==2.0.0
alpaca==1.0.0
alpaca-py==0.18.1
altair==4.2.2
annotated-types==0.6.0
anyio==3.6.2
appdirs==1.4.4
appnope==0.1.3
APScheduler==3.10.4
argon2-cffi==23.1.0
argon2-cffi-bindings==21.2.0
arrow==1.3.0
asttokens==2.2.1
astunparse==1.6.3
async-lru==2.0.4
attrs==22.2.0
Babel==2.15.0
beautifulsoup4==4.12.3
better-exceptions==0.3.3
bleach==6.0.0
blinker==1.5
bottle==0.12.25
cachetools==5.3.0
CD==1.1.0
certifi==2022.12.7
cffi==1.16.0
chardet==5.1.0
charset-normalizer==3.0.1
click==8.1.3
colorama==0.4.6
comm==0.1.4
contourpy==1.0.7
cycler==0.11.0
dash==2.9.1
dash-bootstrap-components==1.4.1
dash-core-components==2.0.0
dash-html-components==2.0.0
dash-table==5.0.0
dateparser==1.1.8
debugpy==1.8.1
decorator==5.1.1
defusedxml==0.7.1
dill==0.3.7
dm-tree==0.1.8
entrypoints==0.4
exceptiongroup==1.1.3
exchange_calendars==4.5.5
executing==1.2.0
fastapi==0.109.2
fastjsonschema==2.19.1
filelock==3.13.1
Flask==2.2.3
flatbuffers==23.5.26
fonttools==4.39.0
fpdf2==2.7.6
fqdn==1.5.1
gast==0.4.0
gitdb==4.0.10
GitPython==3.1.31
google-auth==2.23.0
google-auth-oauthlib==1.0.0
google-pasta==0.2.0
greenlet==3.0.3
grpcio==1.58.0
h11==0.14.0
h5py==3.10.0
html2text==2024.2.26
httpcore==1.0.5
httpx==0.27.0
humanize==4.9.0
icecream==2.1.3
idna==3.4
imageio==2.31.6
importlib-metadata==6.1.0
ipykernel==6.29.4
ipython==8.17.2
ipywidgets==8.1.1
isoduration==20.11.0
itables==2.0.1
itsdangerous==2.1.2
jax==0.4.23
jaxlib==0.4.23
jedi==0.19.1
Jinja2==3.1.2
joblib==1.3.2
json5==0.9.25
jsonpointer==2.4
jsonschema==4.22.0
jsonschema-specifications==2023.12.1
jupyter-events==0.10.0
jupyter-lsp==2.2.5
jupyter_client==8.6.1
jupyter_core==5.7.2
jupyter_server==2.14.0
jupyter_server_terminals==0.5.3
jupyterlab==4.1.8
jupyterlab-widgets==3.0.9
jupyterlab_pygments==0.3.0
jupyterlab_server==2.27.1
kaleido==0.2.1
keras==3.0.2
keras-core==0.1.7
keras-nightly==3.0.3.dev2024010203
keras-nlp-nightly==0.7.0.dev2024010203
keras-tcn @ git+https://github.com/drew2323/keras-tcn.git@4bddb17a02cb2f31c9fe2e8f616b357b1ddb0e11
kiwisolver==1.4.4
korean-lunar-calendar==0.3.1
libclang==16.0.6
lightweight-charts @ git+https://github.com/drew2323/lightweight-charts-python.git@2b9f238a4242d958bc863b6209bf6444786477c5
llvmlite==0.39.1
Markdown==3.4.3
markdown-it-py==2.2.0
MarkupSafe==2.1.2
matplotlib==3.8.2
matplotlib-inline==0.1.6
mdurl==0.1.2
mistune==3.0.2
ml-dtypes==0.3.1
mlroom @ git+https://github.com/drew2323/mlroom.git@692900e274c4e0542d945d231645c270fc508437
mplfinance==0.12.10b0
msgpack==1.0.4
mypy-extensions==1.0.0
namex==0.0.7
nbclient==0.10.0
nbconvert==7.16.4
nbformat==5.10.4
nest-asyncio==1.6.0
newtulipy==0.4.6
notebook_shim==0.2.4
numba==0.56.4
numpy==1.23.5
oauthlib==3.2.2
opt-einsum==3.3.0
orjson==3.9.10
overrides==7.7.0
packaging==23.0
pandas==2.2.1
pandas_market_calendars==4.4.1
pandocfilters==1.5.1
param==1.13.0
parso==0.8.3
patsy==0.5.6
pexpect==4.8.0
Pillow==9.4.0
platformdirs==4.2.0
plotly==5.22.0
prometheus_client==0.20.0
prompt-toolkit==3.0.39
proto-plus==1.22.2
protobuf==3.20.3
proxy-tools==0.1.0
psutil==5.9.8
ptyprocess==0.7.0
pure-eval==0.2.2
pyarrow==11.0.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.22
pyct==0.5.0
pydantic==2.6.4
pydantic_core==2.16.3
pydeck==0.8.0
Pygments==2.14.0
pyinstrument==4.5.3
pyluach==2.2.0
Pympler==1.0.1
pyobjc-core==10.3
pyobjc-framework-Cocoa==10.3
pyobjc-framework-Security==10.3
pyobjc-framework-WebKit==10.3
pyparsing==3.0.9
pyrsistent==0.19.3
pysos==1.3.0
python-call-graph==2.1.2
python-dateutil==2.8.2
python-dotenv==1.0.0
python-json-logger==2.0.7
python-multipart==0.0.6
pytz==2022.7.1
pytz-deprecation-shim==0.1.0.post0
pyviz-comms==2.2.1
PyWavelets==1.5.0
pywebview==5.1
PyYAML==6.0
pyzmq==25.1.2
referencing==0.35.1
regex==2023.10.3
requests==2.31.0
requests-oauthlib==1.3.1
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rich==13.3.1
rpds-py==0.18.0
rsa==4.9
schedule==1.2.1
scikit-learn==1.3.2
scipy==1.11.2
seaborn==0.12.2
semver==2.13.0
Send2Trash==1.8.3
six==1.16.0
smmap==5.0.0
sniffio==1.3.0
soupsieve==2.5
SQLAlchemy==2.0.27
sseclient-py==1.7.2
stack-data==0.6.3
starlette==0.36.3
statsmodels==0.14.1
streamlit==1.20.0
structlog==23.1.0
TA-Lib==0.4.28
tb-nightly==2.16.0a20240102
tenacity==8.2.2
tensorboard==2.15.1
tensorboard-data-server==0.7.1
tensorflow-addons==0.23.0
tensorflow-estimator==2.15.0
tensorflow-io-gcs-filesystem==0.34.0
termcolor==2.3.0
terminado==0.18.1
tf-estimator-nightly==2.14.0.dev2023080308
tf-nightly==2.16.0.dev20240101
tf_keras-nightly==2.16.0.dev2023123010
threadpoolctl==3.2.0
tinycss2==1.3.0
tinydb==4.7.1
tinydb-serialization==2.1.0
tinyflux==0.4.0
toml==0.10.2
tomli==2.0.1
toolz==0.12.0
tornado==6.2
tqdm==4.65.0
traitlets==5.13.0
typeguard==2.13.3
types-python-dateutil==2.9.0.20240316
typing_extensions==4.9.0
tzdata==2023.2
tzlocal==4.3
uri-template==1.3.0
urllib3==1.26.14
uvicorn==0.21.1
-e git+https://github.com/drew2323/v2trading.git@7a283a127e8b11914cb2ba0ad5ef551f5a398f62#egg=v2realbot
validators==0.20.0
vectorbtpro @ file:///Users/davidbrazda/Downloads/vectorbt.pro-develop
wcwidth==0.2.9
webcolors==1.13
webencodings==0.5.1
websocket-client==1.7.0
websockets==11.0.3
Werkzeug==2.2.3
widgetsnbextension==4.0.9
wrapt==1.14.1
zipp==3.15.0