{
 "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 BATCH\n",
    "# res, df = load_batch(batch_id=\"0fb5043a\", #0fb5043a  bde6d0be\n",
    "#                      space_resolution_evenly=False,\n",
    "#                      indicators_columns=[\"Rsi14\"],\n",
    "#                      main_session_only=True,\n",
    "#                      verbose = False)\n",
    "# if res < 0:\n",
    "#     print(\"Error\" + str(res) + str(df))\n",
    "# df = df[\"bars\"]\n",
    "\n",
    "# #df\n",
    "\n",
    "# basic_data = vbt.Data.from_data(vbt.symbol_dict({\"BAC\": df}), tz_convert=zoneNY)\n",
    "# #m1_data = basic_data[['Open', 'High', 'Low', 'Close', 'Volume']]\n",
    "# basic_data = basic_data.transform(lambda df: df.between_time('09:30', '16:00'))\n",
    "\n",
    "#LOAD FROM PARQUET\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
}
