Initial commit after copying files from flawed repository
This commit is contained in:
385
research/basic.ipynb
Normal file
385
research/basic.ipynb
Normal file
@ -0,0 +1,385 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from v2realbot.tools.loadbatch import load_batch\n",
|
||||
"from v2realbot.utils.utils import zoneNY, DATA_DIR\n",
|
||||
"import pandas as pd\n",
|
||||
"import numpy as np\n",
|
||||
"import vectorbtpro as vbt\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": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"batch_id = \"e44a5075\"\n",
|
||||
"# res, df = load_batch(batch_id=batch_id,\n",
|
||||
"# space_resolution_evenly=False,\n",
|
||||
"# indicators_columns=[\"Rsi14\"],\n",
|
||||
"# main_session_only=True)\n",
|
||||
"# if res < 0:\n",
|
||||
"# print(\"Error\" + str(res) + str(df))\n",
|
||||
"# df = df[\"bars\"]\n",
|
||||
"# df.info()\n",
|
||||
"# df.head()\n",
|
||||
"# #df.ptable()\n",
|
||||
"# df.to_pickle(DATA_DIR+\"/\"+f'{batch_id}.pickle')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## FILTERING"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df = pd.read_pickle(DATA_DIR+\"/\"+f'{batch_id}.pickle')\n",
|
||||
"df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"#naloadujeme do vbt symbol as column\n",
|
||||
"basic_data = vbt.Data.from_data({\"BAC\": df}, tz_convert=zoneNY)\n",
|
||||
"start_date = pd.Timestamp('2024-03-12 09:30', tz=zoneNY)\n",
|
||||
"end_date = pd.Timestamp('2024-03-13 16:00', tz=zoneNY)\n",
|
||||
"\n",
|
||||
"#filter date\n",
|
||||
"#basic_data = basic_data.transform(lambda df: df[df.index.date == start_date.date()])\n",
|
||||
"#filter range\n",
|
||||
"basic_data = basic_data.transform(lambda df: df[(df.index >= start_date) & (df.index <= end_date)])\n",
|
||||
"#filtered_data = basic_data.transform(lambda df: df[(df.index >= start_date) & (df.index <= end_date)])\n",
|
||||
"# #range filtered_data = data[(data.index >= start_date) & (data.index <= end_date)\n",
|
||||
"#df.between_time('09:30', '16:00')\n",
|
||||
"#(df.index.time >= pd.Timestamp('09:30').time()) & (df.index.time <= pd.Timestamp('16:00').time())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# basic_data.data[\"BAC\"]\n",
|
||||
"rsi14"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#b = filtered_data.get().iloc[100:200] #b[[\"Open\",\"High\"]]\n",
|
||||
"rsi14 = basic_data.data[\"BAC\"][\"Rsi14\"].rename(\"Rsi14\")\n",
|
||||
"#create subploit\n",
|
||||
"fig = vbt.make_subplots(rows=2, cols=1, shared_xaxes=True, specs=[[{\"secondary_y\": True}], [{\"secondary_y\": False}]])\n",
|
||||
"rsi14.vbt.plot(add_trace_kwargs=dict(row=1, col=1, secondary_y=True),fig=fig)\n",
|
||||
"basic_data.data[\"BAC\"].vbt.ohlcv.plot(add_trace_kwargs=dict(row=1, col=1, secondary_y=False), fig=fig)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"run_rsi = vbt.talib_func(\"rsi\")\n",
|
||||
"rsi_new = run_rsi(basic_data.vwap, timeperiod=15)\n",
|
||||
"rsi_new = rsi_new.fillna(0)\n",
|
||||
"# print(rsi_new)\n",
|
||||
"# print(dir(rsi_new))\n",
|
||||
"rsi14 = basic_data.data[\"BAC\"][\"Rsi14\"]\n",
|
||||
"# print(rsi14)\n",
|
||||
"\n",
|
||||
"#zkombinujeme do stejneho dataframe skrz sloupce (axis1)\n",
|
||||
"# combined_df = pd.concat([rsi_new, rsi14], axis=1)\n",
|
||||
"# combined_df\n",
|
||||
"\n",
|
||||
"#create subplot\n",
|
||||
"fig = vbt.make_subplots(rows=1, cols=1, shared_xaxes=True)\n",
|
||||
"\n",
|
||||
"plot_rsi = vbt.talib_plot_func(\"rsi\")\n",
|
||||
"plot_rsi(rsi_new, fig=fig)\n",
|
||||
"plot_rsi(rsi14, fig=fig)\n",
|
||||
"fig.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"entries = rsi_new.vbt.crossed_below(30)\n",
|
||||
"entries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"exits = rsi_new.vbt.crossed_above(70)\n",
|
||||
"exits "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def plot_rsi(close, rsi, entries, exits):\n",
|
||||
" fig = vbt.make_subplots(rows=2, cols=1, shared_xaxes=True, specs=[[{\"secondary_y\": True}], [{\"secondary_y\": False}]])\n",
|
||||
" basic_data.data[\"BAC\"].vbt.ohlcv.plot(add_trace_kwargs=dict(row=1, col=1, secondary_y=True),fig=fig)\n",
|
||||
" rsi.vbt.plot(fig=fig, add_trace_kwargs=dict(row=1, col=1, secondary_y=False), trace_kwargs=dict(line=dict(color='grey', width=1.5)))\n",
|
||||
" #close.vbt.plot(fig=fig, add_trace_kwargs=dict(row=1, col=1, secondary_y=True))\n",
|
||||
" entries.vbt.signals.plot_as_entries(y=close, fig=fig, add_trace_kwargs=dict(row=1, col=1, secondary_y=True))\n",
|
||||
" exits.vbt.signals.plot_as_exits(y=close, fig=fig, add_trace_kwargs=dict(row=1, col=1, secondary_y=True))\n",
|
||||
" return fig\n",
|
||||
"\n",
|
||||
"close = basic_data.get(\"Close\")\n",
|
||||
"\n",
|
||||
"print(entries)\n",
|
||||
"\n",
|
||||
"plot_rsi(close, rsi_new, entries, exits).show()\n",
|
||||
"\n",
|
||||
"clean_entries, clean_exits = entries.vbt.signals.clean(exits) \n",
|
||||
"\n",
|
||||
"plot_rsi(close, rsi_new, clean_entries, clean_exits).show()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"clean_entries.vbt.signals.total() \n",
|
||||
"clean_exits.vbt.signals.total() "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"index = basic_data.wrapper.index\n",
|
||||
"\n",
|
||||
"#minutes from market open\n",
|
||||
"market_open_time = pd.to_timedelta('09:30:00')\n",
|
||||
"\n",
|
||||
"# Calculate the market open datetime for each day\n",
|
||||
"market_opens = index.normalize() + market_open_time\n",
|
||||
"\n",
|
||||
"minutes_from_open = (index - market_opens).total_seconds() / 60\n",
|
||||
"# Ensuring the result is a Series\n",
|
||||
"minutes_from_open = pd.Series(minutes_from_open, index=index)\n",
|
||||
"\n",
|
||||
"#minutes_from_open.values\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"symbol_wrapper = basic_data.get_symbol_wrapper()\n",
|
||||
"\n",
|
||||
"@vbt.njit\n",
|
||||
"def elapsed_minutes_from_open_nb(time_in_ns):\n",
|
||||
" market_opens_in_minute = 570 # 9 hours * 60 minutes + 30 minutes\n",
|
||||
" current_minute = vbt.dt_nb.hour_nb(time_in_ns) * 60 + vbt.dt_nb.minute_nb(time_in_ns)\n",
|
||||
" #print(\"current_minutes\", current_minutes)\n",
|
||||
" # Calculate elapsed minutes since market open at 9:30 AM\n",
|
||||
" minutes_from_open = current_minute - market_opens_in_minute\n",
|
||||
" print( \"elapsed_from_open\", minutes_from_open)\n",
|
||||
" return minutes_from_open if minutes_from_open >= 0 else 0\n",
|
||||
"\n",
|
||||
"@vbt.njit\n",
|
||||
"def entry_place_func_nb(c, low, close, time_in_ns, rsi14, window_open, window_close):\n",
|
||||
" # if c.from_i == 0: # (1)!\n",
|
||||
" # c.out[0] = True\n",
|
||||
" # return -1\n",
|
||||
" # print(\"ted\")\n",
|
||||
" # print(c.from_i)\n",
|
||||
" #exit_i = c.from_i - c.wait # (2)!\n",
|
||||
" #exit_price = close[exit_i, c.col] # (3)!\n",
|
||||
" #hit_price = exit_price * (1 - th)\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",
|
||||
"#whether the date changed\n",
|
||||
"# day_changed_nb(\n",
|
||||
"# ts1,\n",
|
||||
"# ts2\n",
|
||||
"# )\n",
|
||||
"\n",
|
||||
"# h_ns(ts1) int\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"@vbt.njit\n",
|
||||
"def 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",
|
||||
"\n",
|
||||
" \n",
|
||||
"\n",
|
||||
"\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 high[i, c.col] >= hit_price or close[i, c.col] <= stop_price :\n",
|
||||
" return out_i\n",
|
||||
" return -1\n",
|
||||
"\n",
|
||||
"index = basic_data.wrapper.index\n",
|
||||
"\n",
|
||||
"#minutes from market open\n",
|
||||
"market_open_time = pd.to_timedelta('09:30:00')\n",
|
||||
"\n",
|
||||
"# Calculate the market open datetime for each day\n",
|
||||
"market_opens = index.normalize() + market_open_time\n",
|
||||
"\n",
|
||||
"minutes_from_open = (index - market_opens).total_seconds() / 60\n",
|
||||
"\n",
|
||||
"print(minutes_from_open)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#index 9:30 az 10:00\n",
|
||||
"time_entry_window = ((index.time >= pd.Timestamp(\"09:30:00\").time())&\n",
|
||||
" (index.time <= pd.Timestamp(\"14:00:00\").time()))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"print(time_entry_window)\n",
|
||||
"print(rsi_new)\n",
|
||||
"rsi_entries = rsi_new.vbt.crossed_below(64)\n",
|
||||
"rsi_entries = rsi_entries < 40\n",
|
||||
"rsi_entries_array = rsi_entries.vbt.to_1d_array()\n",
|
||||
"print(rsi_entries_array)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"entries, exits = vbt.pd_acc.signals.generate_both( # (6)!\n",
|
||||
" symbol_wrapper.shape,\n",
|
||||
" entry_place_func_nb=entry_place_func_nb,\n",
|
||||
" #timeindex to ns to numba\n",
|
||||
" entry_place_args=(vbt.Rep(\"low\"), vbt.Rep(\"close\"), vbt.dt.to_ns(basic_data.wrapper.index), vbt.Rep(\"rsi14\"), 0, 380), # (7)!\n",
|
||||
" exit_place_func_nb=exit_place_func_nb,\n",
|
||||
" exit_place_args=(vbt.Rep(\"high\"), vbt.Rep(\"close\"), vbt.dt.to_ns(basic_data.wrapper.index), 0.001, 0.001),\n",
|
||||
" wrapper=symbol_wrapper,\n",
|
||||
" broadcast_named_args=dict( # (8)!\n",
|
||||
" high=basic_data.get(\"High\"),\n",
|
||||
" low=basic_data.get(\"Low\"),\n",
|
||||
" close=basic_data.get(\"Close\"),\n",
|
||||
" rsi14=basic_data.get(\"Rsi14\"),\n",
|
||||
" window_open=10,\n",
|
||||
" window_close=60\n",
|
||||
" ),\n",
|
||||
" broadcast_kwargs=dict(post_func=np.asarray) # (9)!\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"plot_rsi(close, rsi_new, entries, exits).show()\n",
|
||||
"\n",
|
||||
"# fig = basic_data.plot(\n",
|
||||
"# symbol=\"BAC\", \n",
|
||||
"# ohlc_trace_kwargs=dict(opacity=0.5), \n",
|
||||
"# plot_volume=False\n",
|
||||
"# )\n",
|
||||
"\n",
|
||||
"# #rsi_entries.vbt.plot(fig=fig)\n",
|
||||
"# entries.vbt.signals.plot_as_entries(\n",
|
||||
"# y=close, fig=fig)\n",
|
||||
"# exits.vbt.signals.plot_as_exits(\n",
|
||||
"# y=close, fig=fig)\n",
|
||||
"# fig.show() # (10)!"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
95
research/chartMultipleMarkers.ipynb
Normal file
95
research/chartMultipleMarkers.ipynb
Normal file
@ -0,0 +1,95 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import vectorbtpro as vbt\n",
|
||||
"from lightweight_charts import chart, Panel\n",
|
||||
"\n",
|
||||
"# Pulling ETH-USD data\n",
|
||||
"data = vbt.YFData.pull(\"ETH-USD\")\n",
|
||||
"close = data.close\n",
|
||||
"high = data.high\n",
|
||||
"low = data.low\n",
|
||||
"\n",
|
||||
"# Define a simple moving average crossover strategy using EWM\n",
|
||||
"short_ma = vbt.MA.run(close, window=6, wtype=\"exp\").ma\n",
|
||||
"long_ma = vbt.MA.run(close, window=73, wtype=\"exp\").ma\n",
|
||||
"\n",
|
||||
"# Generate signals\n",
|
||||
"long_entries = short_ma > long_ma\n",
|
||||
"long_exits = short_ma < long_ma\n",
|
||||
"short_entries = short_ma < long_ma\n",
|
||||
"short_exits = short_ma > long_ma\n",
|
||||
"\n",
|
||||
"clean_long_entries, clean_long_exits = long_entries.vbt.signals.clean(long_exits)\n",
|
||||
"clean_short_entries, clean_short_exits = short_entries.vbt.signals.clean(short_exits)\n",
|
||||
"\n",
|
||||
"# ohlcv_df = data.ohlcv.get()\n",
|
||||
"\n",
|
||||
"#assume i want to display simple entries or exits on series or ohlcv \n",
|
||||
"#based on tuple positions it determines entries or exits (and set colors and shape accordingly)\n",
|
||||
"pane1 = Panel(\n",
|
||||
" ohlcv=(data.ohlcv.get(), clean_long_entries, clean_short_entries)\n",
|
||||
")\n",
|
||||
"ch = chart([pane1], title=\"Chart with Entry/Exit Markers\", session=None, size=\"s\")\n",
|
||||
"\n",
|
||||
"#if you want to display more entries or exits, use tuples with their colors\n",
|
||||
"pane1 = Panel(\n",
|
||||
" ohlcv=(data.ohlcv.get(),\n",
|
||||
" [(clean_long_entries, \"yellow\"), (clean_short_entries, \"pink\")], #list of entries tuples with color\n",
|
||||
" [(clean_long_exits, \"yellow\"), (clean_short_exits, \"pink\")] #list of exits tuples with color\n",
|
||||
" ), \n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# # Create the chart with the panel\n",
|
||||
"ch = chart([pane1], title=\"Chart with EntryShort/ExitShort (yellow) and EntryLong/ExitLong markers (pink)\", sync=True, session=None, size=\"s\")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# # Add the markers to the chart using markers_set method\n",
|
||||
"# entry_signals = pd.DataFrame({\n",
|
||||
"# 'time': clean_long_entries.index.astype(str),\n",
|
||||
"# 'value': clean_long_entries.values\n",
|
||||
"# }).dropna()\n",
|
||||
"# entry_signals['value'] = entry_signals['value'].astype(bool)\n",
|
||||
"\n",
|
||||
"# ch.markers_set(entry_signals, type='entries')"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
348
research/get_trades_at_once.ipynb
Normal file
348
research/get_trades_at_once.ipynb
Normal file
@ -0,0 +1,348 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Loading trades and vectorized aggregation\n",
|
||||
"Describes how to fetch trades (remote/cached) and use new vectorized aggregation to aggregate bars of given type (time, volume, dollar) and resolution\n",
|
||||
"\n",
|
||||
"`fetch_trades_parallel` enables to fetch trades of given symbol and interval, also can filter conditions and minimum size. return `trades_df`\n",
|
||||
"`aggregate_trades` acceptss `trades_df` and ressolution and type of bars (VOLUME, TIME, DOLLAR) and return aggregated ohlcv dataframe `ohlcv_df`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import numpy as np\n",
|
||||
"from numba import jit\n",
|
||||
"from alpaca.data.historical import StockHistoricalDataClient\n",
|
||||
"from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, DATA_DIR\n",
|
||||
"from alpaca.data.requests import StockTradesRequest\n",
|
||||
"from v2realbot.enums.enums import BarType\n",
|
||||
"import time\n",
|
||||
"from datetime import datetime\n",
|
||||
"from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, zoneNY, send_to_telegram, fetch_calendar_data\n",
|
||||
"import pyarrow\n",
|
||||
"from v2realbot.loader.aggregator_vectorized import fetch_daily_stock_trades, fetch_trades_parallel, generate_time_bars_nb, aggregate_trades\n",
|
||||
"import vectorbtpro as vbt\n",
|
||||
"import v2realbot.utils.config_handler as cfh\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', 20) # Number of rows per page\n",
|
||||
"# pd.set_option('display.float_format', '{:.9f}'.format)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#trade filtering\n",
|
||||
"exclude_conditions = cfh.config_handler.get_val('AGG_EXCLUDED_TRADES') #standard ['C','O','4','B','7','V','P','W','U','Z','F']\n",
|
||||
"minsize = 100\n",
|
||||
"\n",
|
||||
"symbol = \"SPY\"\n",
|
||||
"#datetime in zoneNY \n",
|
||||
"day_start = datetime(2024, 1, 1, 9, 30, 0)\n",
|
||||
"day_stop = datetime(2024, 1, 14, 16, 00, 0)\n",
|
||||
"day_start = zoneNY.localize(day_start)\n",
|
||||
"day_stop = zoneNY.localize(day_stop)\n",
|
||||
"#filename of trades_df parquet, date are in isoformat but without time zone part\n",
|
||||
"dir = DATA_DIR + \"/notebooks/\"\n",
|
||||
"#parquet interval cache contains exclude conditions and minsize filtering\n",
|
||||
"file_trades = dir + f\"trades_df-{symbol}-{day_start.strftime('%Y-%m-%dT%H:%M:%S')}-{day_stop.strftime('%Y-%m-%dT%H:%M:%S')}-{exclude_conditions}-{minsize}.parquet\"\n",
|
||||
"#file_trades = dir + f\"trades_df-{symbol}-{day_start.strftime('%Y-%m-%dT%H:%M:%S')}-{day_stop.strftime('%Y-%m-%dT%H:%M:%S')}.parquet\"\n",
|
||||
"file_ohlcv = dir + f\"ohlcv_df-{symbol}-{day_start.strftime('%Y-%m-%dT%H:%M:%S')}-{day_stop.strftime('%Y-%m-%dT%H:%M:%S')}-{exclude_conditions}-{minsize}.parquet\"\n",
|
||||
"\n",
|
||||
"#PRINT all parquet in directory\n",
|
||||
"import os\n",
|
||||
"files = [f for f in os.listdir(dir) if f.endswith(\".parquet\")]\n",
|
||||
"for f in files:\n",
|
||||
" print(f)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df = fetch_daily_stock_trades(symbol, day_start, day_stop, exclude_conditions=exclude_conditions, minsize=minsize, force_remote=False, max_retries=5, backoff_factor=1)\n",
|
||||
"trades_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#Either load trades or ohlcv from parquet if exists\n",
|
||||
"\n",
|
||||
"#trades_df = fetch_trades_parallel(symbol, day_start, day_stop, exclude_conditions=exclude_conditions, minsize=50, max_workers=20) #exclude_conditions=['C','O','4','B','7','V','P','W','U','Z','F'])\n",
|
||||
"# trades_df.to_parquet(file_trades, engine='pyarrow', compression='gzip')\n",
|
||||
"\n",
|
||||
"trades_df = pd.read_parquet(file_trades,engine='pyarrow')\n",
|
||||
"ohlcv_df = aggregate_trades(symbol=symbol, trades_df=trades_df, resolution=1, type=BarType.TIME)\n",
|
||||
"ohlcv_df.to_parquet(file_ohlcv, engine='pyarrow', compression='gzip')\n",
|
||||
"\n",
|
||||
"# ohlcv_df = pd.read_parquet(file_ohlcv,engine='pyarrow')\n",
|
||||
"# trades_df = pd.read_parquet(file_trades,engine='pyarrow')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#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",
|
||||
"file_name = \"\"\n",
|
||||
"ohlcv_df = pd.read_parquet(file_ohlcv,engine='pyarrow')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"# Calculate daily returns\n",
|
||||
"ohlcv_df['returns'] = ohlcv_df['close'].pct_change().dropna()\n",
|
||||
"#same as above but pct_change is from 3 datapoints back, but only if it is the same date, else na\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Plot the probability distribution curve\n",
|
||||
"plt.figure(figsize=(10, 6))\n",
|
||||
"sns.histplot(df['returns'].dropna(), kde=True, stat='probability', bins=30)\n",
|
||||
"plt.title('Probability Distribution of Daily Returns')\n",
|
||||
"plt.xlabel('Daily Returns')\n",
|
||||
"plt.ylabel('Probability')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import numpy as np\n",
|
||||
"from sklearn.model_selection import train_test_split\n",
|
||||
"from sklearn.preprocessing import StandardScaler\n",
|
||||
"from sklearn.linear_model import LogisticRegression\n",
|
||||
"from sklearn.metrics import accuracy_score\n",
|
||||
"\n",
|
||||
"# Define the intervals from 5 to 20 s, returns for each interval\n",
|
||||
"#maybe use rolling window?\n",
|
||||
"intervals = range(5, 21, 5)\n",
|
||||
"\n",
|
||||
"# Create columns for percentage returns\n",
|
||||
"rolling_window = 50\n",
|
||||
"\n",
|
||||
"# Normalize the returns using rolling mean and std\n",
|
||||
"for N in intervals:\n",
|
||||
" column_name = f'returns_{N}'\n",
|
||||
" rolling_mean = ohlcv_df[column_name].rolling(window=rolling_window).mean()\n",
|
||||
" rolling_std = ohlcv_df[column_name].rolling(window=rolling_window).std()\n",
|
||||
" ohlcv_df[f'norm_{column_name}'] = (ohlcv_df[column_name] - rolling_mean) / rolling_std\n",
|
||||
"\n",
|
||||
"# Display the dataframe with normalized return columns\n",
|
||||
"ohlcv_df\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Calculate the sum of the normalized return columns for each row\n",
|
||||
"ohlcv_df['sum_norm_returns'] = ohlcv_df[[f'norm_returns_{N}' for N in intervals]].sum(axis=1)\n",
|
||||
"\n",
|
||||
"# Sort the DataFrame based on the sum of normalized returns in descending order\n",
|
||||
"df_sorted = ohlcv_df.sort_values(by='sum_norm_returns', ascending=False)\n",
|
||||
"\n",
|
||||
"# Display the top rows with the highest sum of normalized returns\n",
|
||||
"df_sorted\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Drop initial rows with NaN values due to pct_change\n",
|
||||
"ohlcv_df.dropna(inplace=True)\n",
|
||||
"\n",
|
||||
"# Plotting the probability distribution curves\n",
|
||||
"plt.figure(figsize=(14, 8))\n",
|
||||
"for N in intervals:\n",
|
||||
" sns.kdeplot(ohlcv_df[f'returns_{N}'].dropna(), label=f'Returns {N}', fill=True)\n",
|
||||
"\n",
|
||||
"plt.title('Probability Distribution of Percentage Returns')\n",
|
||||
"plt.xlabel('Percentage Return')\n",
|
||||
"plt.ylabel('Density')\n",
|
||||
"plt.legend()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"# Plot the probability distribution curve\n",
|
||||
"plt.figure(figsize=(10, 6))\n",
|
||||
"sns.histplot(ohlcv_df['returns'].dropna(), kde=True, stat='probability', bins=30)\n",
|
||||
"plt.title('Probability Distribution of Daily Returns')\n",
|
||||
"plt.xlabel('Daily Returns')\n",
|
||||
"plt.ylabel('Probability')\n",
|
||||
"plt.show()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#show only rows from ohlcv_df where returns > 0.005\n",
|
||||
"ohlcv_df[ohlcv_df['returns'] > 0.0005]\n",
|
||||
"\n",
|
||||
"#ohlcv_df[ohlcv_df['returns'] < -0.005]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#ohlcv where index = date 2024-03-13 and between hour 12\n",
|
||||
"\n",
|
||||
"a = ohlcv_df.loc['2024-03-13 12:00:00':'2024-03-13 13:00:00']\n",
|
||||
"a"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df.to_parquet(\"trades_df-spy-0111-0111.parquett\", engine='pyarrow', compression='gzip')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df.to_parquet(\"trades_df-spy-111-0516.parquett\", engine='pyarrow', compression='gzip', allow_truncated_timestamps=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df.to_parquet(\"ohlcv_df-spy-111-0516.parquett\", engine='pyarrow', compression='gzip')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"basic_data = vbt.Data.from_data(vbt.symbol_dict({symbol: ohlcv_df}), tz_convert=zoneNY)\n",
|
||||
"vbt.settings['plotting']['auto_rangebreaks'] = True\n",
|
||||
"basic_data.ohlcv.plot()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#access just BCA\n",
|
||||
"#df_filtered = df.loc[\"BAC\"]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
208
research/indcross_parametrized.ipynb
Normal file
208
research/indcross_parametrized.ipynb
Normal file
@ -0,0 +1,208 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"celkovy optimalizacni backtest na vetsim oknu 1 - 300\n",
|
||||
"a možná take to udělat jako parametr\n",
|
||||
"zkusit CV\n",
|
||||
"zobrazit nejak robustnost parametru"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"\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",
|
||||
"res, df = load_batch(batch_id=\"f1ac6651\", #138170bc 0fb5043a bde6d0be f1ac6651\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",
|
||||
"#basic_data.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vbt.open_api_ref(vbt.base)\n",
|
||||
"\n",
|
||||
"vbt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"##na toto udelat crosssvalidationu nebo alespon na testovacim ci jinem obdobi\n",
|
||||
"#take udelat long leg - tato je shortovaci\n",
|
||||
"\n",
|
||||
"#8\t-0.06\t-0.2\t0.0028\t0.0048\t4.156254\n",
|
||||
"\n",
|
||||
"#short combination ok for train(4)/test(0.1) (window 1-90, fe 95-100)\n",
|
||||
"#2,\t-0.02,\t-0.25,\t0.0018,\t0.0068\n",
|
||||
"\n",
|
||||
"#dalsi ok hodnota shortu for train/test 4/1\n",
|
||||
"#70,\t8,\t-0.06,\t-0.2,\t0.0013,\t0.0053\t\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#kombinace bez roc_th, train/test 7/-1.5\n",
|
||||
"#70\t7\t-0.07\t0.0033\t0.0063\n",
|
||||
"\n",
|
||||
"#opet bez roc_th, train(5.77)/test 0.9 - spolus tsl_stop + tsl_th\n",
|
||||
"#29\t7\t-0.09\t0.0033\t0.0068\n",
|
||||
"\n",
|
||||
"#bez roc_th a s trailing sl train/test 8.1/-0.8 \n",
|
||||
"#70\t2\t-0.05\t0.0018\t0.0068\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# TODO:\n",
|
||||
"#- vyzkouset zda nejvyhodnejsi kombinace krom train/testu funguje i na nasledujicich dnech po trainu\n",
|
||||
"# -zkusit najit v short datasetu neco vyhodneho co funguji i na testu\n",
|
||||
"# - dodelat kombinace pro long signaly\n",
|
||||
"# - zkusit walk forward\n",
|
||||
"# - vytvorit vysledkove totoznou na v2realbot\n",
|
||||
"# - podivat se jak detailne funguji tsl_stop a tsl_th\n",
|
||||
"\n",
|
||||
"#70,\t4,\t-0.07,\t0.0048,\t0.0068\t\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"entry_window_closes, mom_timeperiod, mom_th, sl_stop, tp_stop = 8,\t3,\t0.07,\t0.0028,\t0.0033\t\n",
|
||||
"roc_th = 0\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",
|
||||
"\n",
|
||||
"long_signal = momshort.real_crossed_above(mom_th)\n",
|
||||
"\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=entries, exits=exits, tsl_stop=sl_stop, tp_stop = tp_stop, 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": [
|
||||
"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
|
||||
}
|
||||
252
research/ohlc_persistance_test.ipynb
Normal file
252
research/ohlc_persistance_test.ipynb
Normal file
@ -0,0 +1,252 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Test persistance\n",
|
||||
"\n",
|
||||
"ohlcv and trades persistence with bar type and trade filtering and minsize support\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"/OHLCV/\n",
|
||||
" ├── {bar_type}/ (1s)\n",
|
||||
" │ ├── {resolution}/\n",
|
||||
" │ │ ├── {filtered_trades}-{min_trade_size}/\n",
|
||||
" │ │ │ ├── {day}/\n",
|
||||
" │ │ │ │ └── hashedname.parquet\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"import v2realbot.utils.config_handler as cfh\n",
|
||||
"init_notebook_mode(all_interactive=True)\n",
|
||||
"from v2realbot.enums.enums import BarType\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=\"f1ac6651\", #138170bc 0fb5043a bde6d0be f1ac6651\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",
|
||||
"# 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",
|
||||
"# #basic_data.info()\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-25T16_00_00-47BCFOPUVWZ-100.parquet\"\n",
|
||||
"ohlcv_df = pd.read_parquet(dir+file_name,engine='pyarrow')\n",
|
||||
"\n",
|
||||
"#filter ohlcv_df to certain date range (assuming datetime index)\n",
|
||||
"#ohlcv_df = ohlcv_df.loc[\"2024-05-14 09:30\":\"2024-05-15 09:35\"]\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)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#basic_data.data[\"BAC\"].info()\n",
|
||||
"#ohlcv_df group by week number of rows\n",
|
||||
"# ohlcv_df['close'].groupby(pd.Grouper(freq='ME')).mean()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#trade filtering\n",
|
||||
"exclude_conditions = cfh.config_handler.get_val('AGG_EXCLUDED_TRADES') #standard ['C','O','4','B','7','V','P','W','U','Z','F']\n",
|
||||
"minsize = 100\n",
|
||||
"exclude_conditions_str = ''.join(exclude_conditions)\n",
|
||||
"exclude_conditions_str"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"basic_data.data[\"BAC\"].info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Aim is to store\n",
|
||||
"OHLCV grouped by symbol, day, resolution\n",
|
||||
"and \n",
|
||||
"bar type\n",
|
||||
"excluded_conditions\n",
|
||||
"minsize\n",
|
||||
"main session"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"bartype= BarType.TIME\n",
|
||||
"resolution = \"1s\"\n",
|
||||
"trade_filter = exclude_conditions_str+\"-\"+str(minsize)\n",
|
||||
"dir = \"/OHLCV/\"+bartype+\"/\"+resolution+\"/\"+trade_filter+\"/\"\n",
|
||||
"#dir = DATA_DIR + dir\n",
|
||||
"basic_data.to_parquet(partition_by=\"day\", keep_groupby_names=False, path_or_buf=dir, mkdir_kwargs=dict(mkdir=True)) \n",
|
||||
"#partition_by=\"day\",\n",
|
||||
"\n",
|
||||
"#naloaduje partitionvana 1s data skrz 90 dni za 2s\n",
|
||||
"#day_data = vbt.ParquetData.pull(\"BAC\", paths=dir, filters=[(\"group\", \">\", \"2024-01-02\"),(\"group\", \"<=\", \"2024-01-09\")]) #, \n",
|
||||
"# day_data[\"2024-05-01\":\"2024-05-14\"].get()\n",
|
||||
"\n",
|
||||
"# day_data.data[\"BAC\"].info()\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#naloaduje partitionvana 1s data skrz 90 dni za 2s\n",
|
||||
"day_data = vbt.ParquetData.pull(\"BAC\", paths=dir, filters=[(\"group\", \">=\", \"2024-01-02\"),(\"group\", \"<=\", \"2024-01-09\")]) #, \n",
|
||||
"# day_data[\"2024-05-01\":\"2024-05-14\"].get()\n",
|
||||
"\n",
|
||||
"day_data.data[\"BAC\"].info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"close = basic_data.close\n",
|
||||
"#group by close by day, using pandas grouper\n",
|
||||
"#close.groupby(pd.Grouper(freq='ME')).mean()\n",
|
||||
"\n",
|
||||
"#using Grouper of vectorbtpro\n",
|
||||
"#close.vbt.group_by(pd.Grouper(freq='ME')).mean()\n",
|
||||
"\n",
|
||||
"#basic_data.wrapper.get_columns()\n",
|
||||
"basic_data.wrapper.get_freq()\n",
|
||||
"# vbt.pdir(basic_data.wrapper)\n",
|
||||
"# basic_data.wrapper\n",
|
||||
"basic_data.wrapper.grouper.is_grouped()\n",
|
||||
"\n",
|
||||
"vbt.pdir(basic_data.wrapper.grouper)\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"grouper = basic_data.wrapper.index.vbt.get_grouper(\"ME\")\n",
|
||||
"\n",
|
||||
"for group, group_idx in grouper:\n",
|
||||
" print(group, group_idx)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#prevede 1milion dat (6mes 1s) na dict za 10ss\n",
|
||||
"df = day_data.data[\"BAC\"]\n",
|
||||
"df_dict = df.to_dict(orient='list')\n",
|
||||
"\n",
|
||||
"# Convert the index (which is the time) to a list of float timestamps\n",
|
||||
"df_dict['time'] = [timestamp.timestamp() for timestamp in df.index]\n",
|
||||
"\n",
|
||||
"df_dict"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
458
research/prepare_aggregatied_data.ipynb
Normal file
458
research/prepare_aggregatied_data.ipynb
Normal file
@ -0,0 +1,458 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Loading trades and vectorized aggregation\n",
|
||||
"This notebook fetches the trades from remote or local cache and aggregates them to bars of given type (time, volume, dollar) and resolution\n",
|
||||
"\n",
|
||||
"`fetch_trades_parallel` enables to fetch trades of given symbol and interval, also can filter conditions and minimum size. return `trades_df`\n",
|
||||
"`aggregate_trades` acceptss `trades_df` and ressolution and type of bars (VOLUME, TIME, DOLLAR) and return aggregated ohlcv dataframe `ohlcv_df`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
"import pandas as pd\n",
|
||||
"import numpy as np\n",
|
||||
"from numba import jit\n",
|
||||
"from alpaca.data.historical import StockHistoricalDataClient\n",
|
||||
"from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, DATA_DIR\n",
|
||||
"from alpaca.data.requests import StockTradesRequest\n",
|
||||
"from v2realbot.enums.enums import BarType\n",
|
||||
"import time\n",
|
||||
"from datetime import datetime\n",
|
||||
"from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, zoneNY, send_to_telegram, fetch_calendar_data\n",
|
||||
"import pyarrow\n",
|
||||
"from v2realbot.loader.aggregator_vectorized import fetch_daily_stock_trades, fetch_trades_parallel, generate_time_bars_nb, aggregate_trades\n",
|
||||
"import vectorbtpro as vbt\n",
|
||||
"import v2realbot.utils.config_handler as cfh\n",
|
||||
"from appdirs import user_data_dir\n",
|
||||
"from pathlib import Path\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', 20) # Number of rows per page\n",
|
||||
"# pd.set_option('display.float_format', '{:.9f}'.format)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#trade filtering\n",
|
||||
"exclude_conditions = cfh.config_handler.get_val('AGG_EXCLUDED_TRADES') #standard ['C','O','4','B','7','V','P','W','U','Z','F']\n",
|
||||
"minsize = 100\n",
|
||||
"\n",
|
||||
"symbol = \"BAC\"\n",
|
||||
"#datetime in zoneNY \n",
|
||||
"day_start = datetime(2023, 1, 1, 9, 30, 0)\n",
|
||||
"day_stop = datetime(2024, 5, 25, 15, 30, 0)\n",
|
||||
"day_start = zoneNY.localize(day_start)\n",
|
||||
"day_stop = zoneNY.localize(day_stop)\n",
|
||||
"#filename of trades_df parquet, date are in isoformat but without time zone part\n",
|
||||
"dir = DATA_DIR + \"/notebooks/\"\n",
|
||||
"#parquet interval cache contains exclude conditions and minsize filtering\n",
|
||||
"file_trades = dir + f\"trades_df-{symbol}-{day_start.strftime('%Y-%m-%dT%H_%M_%S')}-{day_stop.strftime('%Y-%m-%dT%H_%M_%S')}-{''.join(exclude_conditions)}-{minsize}.parquet\"\n",
|
||||
"#file_trades = dir + f\"trades_df-{symbol}-{day_start.strftime('%Y-%m-%dT%H:%M:%S')}-{day_stop.strftime('%Y-%m-%dT%H:%M:%S')}.parquet\"\n",
|
||||
"file_ohlcv = dir + f\"ohlcv_df-{symbol}-{day_start.strftime('%Y-%m-%dT%H_%M_%S')}-{day_stop.strftime('%Y-%m-%dT%H_%M_%S')}-{''.join(exclude_conditions)}-{minsize}.parquet\"\n",
|
||||
"print(file_trades)\n",
|
||||
"print(file_ohlcv)\n",
|
||||
"#PRINT all parquet in directory\n",
|
||||
"import os\n",
|
||||
"files = [f for f in os.listdir(dir) if f.endswith(\".parquet\")]\n",
|
||||
"for f in files:\n",
|
||||
" print(f)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#Either load trades or ohlcv from parquet if exists\n",
|
||||
"#trades_df = fetch_trades_parallel(symbol, day_start, day_stop, exclude_conditions=exclude_conditions, minsize=minsize, max_workers=30) #exclude_conditions=['C','O','4','B','7','V','P','W','U','Z','F'])\n",
|
||||
"#trades_df.to_parquet(file_trades, engine='pyarrow', compression='gzip')\n",
|
||||
"#trades_df.to_parquet(file_trades, engine='pyarrow', compression='gzip')\n",
|
||||
"#filenames = [dir+\"trades_df-BAC-2024-01-01T09_30_00-2024-05-14T16_00_00-CO4B7VPWUZF-100.parquet\",dir+\"trades_df-BAC-2024-05-15T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\"]\n",
|
||||
"trades_df = pd.read_parquet(dir+\"trades_df-BAC-2023-01-01T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\",engine='pyarrow')\n",
|
||||
"#focused = trades_df.loc[\"2024-02-16 11:23:11\":\"2024-02-16 11:24:26\"]\n",
|
||||
"#focused\n",
|
||||
"ohlcv_df = aggregate_trades(symbol=symbol, trades_df=trades_df, resolution=1, type=BarType.TIME)\n",
|
||||
"ohlcv_df.to_parquet(file_ohlcv, engine='pyarrow', compression='gzip')\n",
|
||||
"\n",
|
||||
"#ohlcv_df = pd.read_parquet(file_ohlcv,engine='pyarrow')\n",
|
||||
"# trades_df = pd.read_parquet(file_trades,engine='pyarrow')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df = None\n",
|
||||
"ohlcv_df = None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#ohlcv_df.info()\n",
|
||||
"#trades_df.info()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"a = trades_df.loc[(\"BAC\", \"2024-02-16 09:30\"):(\"BAC\",\"2024-02-16 09:32:11\")]\n",
|
||||
"a"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#trades_df.info()\n",
|
||||
"focused = trades_df.loc[(\"BAC\", \"2024-02-16 09:30:00\"):(\"BAC\", \"2024-02-16 10:24:26\")]\n",
|
||||
"focused"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df.loc[\"2024-02-16 09:30:00\":\"2024-02-16 10:24:26\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"focohlc = ohlcv_df.loc[\"2024-02-16 09:30:00\":\"2024-02-16 10:24:26\"]\n",
|
||||
"focohlc\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"focohlc.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#trades_df.to_parquet(dir + \"trades_df-BAC-2024-01-01T09:30:00-2024-05-14T16:00:00-CO4B7VPWUZF-100.parquet\", engine='pyarrow', compression='gzip')\n",
|
||||
"#trades_df = pd.read_parquet(dir + \"trades_df-BAC-2024-01-01T09:30:00-2024-05-14T16:00:00-CO4B7VPWUZF-100.parquet\",engine='pyarrow')\n",
|
||||
"\n",
|
||||
"#trades_df.to_parquet(file_trades, engine='pyarrow', compression='gzip')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"file_trades"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#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",
|
||||
"file_name = \"\"\n",
|
||||
"ohlcv_df = pd.read_parquet(file_ohlcv,engine='pyarrow')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"# Calculate daily returns\n",
|
||||
"ohlcv_df['returns'] = ohlcv_df['close'].pct_change().dropna()\n",
|
||||
"#same as above but pct_change is from 3 datapoints back, but only if it is the same date, else na\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Plot the probability distribution curve\n",
|
||||
"plt.figure(figsize=(10, 6))\n",
|
||||
"sns.histplot(df['returns'].dropna(), kde=True, stat='probability', bins=30)\n",
|
||||
"plt.title('Probability Distribution of Daily Returns')\n",
|
||||
"plt.xlabel('Daily Returns')\n",
|
||||
"plt.ylabel('Probability')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import numpy as np\n",
|
||||
"from sklearn.model_selection import train_test_split\n",
|
||||
"from sklearn.preprocessing import StandardScaler\n",
|
||||
"from sklearn.linear_model import LogisticRegression\n",
|
||||
"from sklearn.metrics import accuracy_score\n",
|
||||
"\n",
|
||||
"# Define the intervals from 5 to 20 s, returns for each interval\n",
|
||||
"#maybe use rolling window?\n",
|
||||
"intervals = range(5, 21, 5)\n",
|
||||
"\n",
|
||||
"# Create columns for percentage returns\n",
|
||||
"rolling_window = 50\n",
|
||||
"\n",
|
||||
"# Normalize the returns using rolling mean and std\n",
|
||||
"for N in intervals:\n",
|
||||
" column_name = f'returns_{N}'\n",
|
||||
" rolling_mean = ohlcv_df[column_name].rolling(window=rolling_window).mean()\n",
|
||||
" rolling_std = ohlcv_df[column_name].rolling(window=rolling_window).std()\n",
|
||||
" ohlcv_df[f'norm_{column_name}'] = (ohlcv_df[column_name] - rolling_mean) / rolling_std\n",
|
||||
"\n",
|
||||
"# Display the dataframe with normalized return columns\n",
|
||||
"ohlcv_df\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Calculate the sum of the normalized return columns for each row\n",
|
||||
"ohlcv_df['sum_norm_returns'] = ohlcv_df[[f'norm_returns_{N}' for N in intervals]].sum(axis=1)\n",
|
||||
"\n",
|
||||
"# Sort the DataFrame based on the sum of normalized returns in descending order\n",
|
||||
"df_sorted = ohlcv_df.sort_values(by='sum_norm_returns', ascending=False)\n",
|
||||
"\n",
|
||||
"# Display the top rows with the highest sum of normalized returns\n",
|
||||
"df_sorted\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Drop initial rows with NaN values due to pct_change\n",
|
||||
"ohlcv_df.dropna(inplace=True)\n",
|
||||
"\n",
|
||||
"# Plotting the probability distribution curves\n",
|
||||
"plt.figure(figsize=(14, 8))\n",
|
||||
"for N in intervals:\n",
|
||||
" sns.kdeplot(ohlcv_df[f'returns_{N}'].dropna(), label=f'Returns {N}', fill=True)\n",
|
||||
"\n",
|
||||
"plt.title('Probability Distribution of Percentage Returns')\n",
|
||||
"plt.xlabel('Percentage Return')\n",
|
||||
"plt.ylabel('Density')\n",
|
||||
"plt.legend()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"# Plot the probability distribution curve\n",
|
||||
"plt.figure(figsize=(10, 6))\n",
|
||||
"sns.histplot(ohlcv_df['returns'].dropna(), kde=True, stat='probability', bins=30)\n",
|
||||
"plt.title('Probability Distribution of Daily Returns')\n",
|
||||
"plt.xlabel('Daily Returns')\n",
|
||||
"plt.ylabel('Probability')\n",
|
||||
"plt.show()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#show only rows from ohlcv_df where returns > 0.005\n",
|
||||
"ohlcv_df[ohlcv_df['returns'] > 0.0005]\n",
|
||||
"\n",
|
||||
"#ohlcv_df[ohlcv_df['returns'] < -0.005]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#ohlcv where index = date 2024-03-13 and between hour 12\n",
|
||||
"\n",
|
||||
"a = ohlcv_df.loc['2024-03-13 12:00:00':'2024-03-13 13:00:00']\n",
|
||||
"a"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df.to_parquet(\"trades_df-spy-0111-0111.parquett\", engine='pyarrow', compression='gzip')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trades_df.to_parquet(\"trades_df-spy-111-0516.parquett\", engine='pyarrow', compression='gzip', allow_truncated_timestamps=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ohlcv_df.to_parquet(\"ohlcv_df-spy-111-0516.parquett\", engine='pyarrow', compression='gzip')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"basic_data = vbt.Data.from_data(vbt.symbol_dict({symbol: ohlcv_df}), tz_convert=zoneNY)\n",
|
||||
"vbt.settings['plotting']['auto_rangebreaks'] = True\n",
|
||||
"basic_data.ohlcv.plot()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#access just BCA\n",
|
||||
"#df_filtered = df.loc[\"BAC\"]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
467
research/rsi_alpaca.ipynb
Normal file
467
research/rsi_alpaca.ipynb
Normal file
@ -0,0 +1,467 @@
|
||||
{
|
||||
"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",
|
||||
"from datetime import timedelta, datetime\n",
|
||||
"import vectorbtpro as vbt\n",
|
||||
"import os\n",
|
||||
"from itables import init_notebook_mode, show\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",
|
||||
"# Alpaca API credentials\n",
|
||||
"ALPACA_API_KEY = os.environ.get('ACCOUNT1_PAPER_API_KEY')\n",
|
||||
"ALPACA_API_SECRET = os.environ.get('ACCOUNT1_PAPER_SECRET_KEY')\n",
|
||||
"\n",
|
||||
"# Initialize Alpaca data client\n",
|
||||
"alpaca_data = vbt.AlpacaData.set_custom_settings(client_config=dict(\n",
|
||||
" api_key=ALPACA_API_KEY,\n",
|
||||
" secret_key=ALPACA_API_SECRET\n",
|
||||
" )\n",
|
||||
")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Fetch Data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Define the symbol, start, and end dates for your data\n",
|
||||
"symbol = 'BAC'\n",
|
||||
"start_date = datetime.now() - timedelta(days=10) # Last 30 days\n",
|
||||
"end_date = datetime.now() - timedelta(days=1) # yesterday\n",
|
||||
"time_interval = '1T' # 1-minute intervals '1 minute'\n",
|
||||
"\n",
|
||||
"basic_data = vbt.AlpacaData.pull([\"BAC\"], start=start_date, end=end_date, timeframe=time_interval, tz=\"America/New_York\")\n",
|
||||
"basic_data = basic_data.transform(lambda x: x.between_time(\"9:30\",\"16:00\"))\n",
|
||||
"#basic_data.data[\"BAC\"].vbt.ohlcv.plot()\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', '2024-04-23']).tz_localize('US/Eastern')\n",
|
||||
"# filtered_df = df.loc[df.index.normalize().isin(dates_of_interest)]\n",
|
||||
"\n",
|
||||
"# df = filtered_df\n",
|
||||
"# df.info()\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_data = m15_data.transform(lambda x: x.between_time(\"9:30\",\"15:59\"))\n",
|
||||
"\n",
|
||||
"m15 = m15_data.data[\"BAC\"]\n",
|
||||
"\n",
|
||||
"m15.vbt.ohlcv.plot()\n",
|
||||
"\n",
|
||||
"m15\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": [
|
||||
"# Calculate VWAP"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#WWAP\n",
|
||||
"vbt.phelp(vbt.VWAP.run)\n",
|
||||
"close = m1_data.close\n",
|
||||
"high = m1_data.high\n",
|
||||
"low = m1_data.low\n",
|
||||
"volume = m1_data.volume\n",
|
||||
"vwapD = vbt.VWAP.run(high, low, close, volume, anchor=\"D\")\n",
|
||||
"# vwapT = vbt.VWAP.run(high, low, close, volume, anchor=\"T\")\n",
|
||||
"\n",
|
||||
"#vwap.vwap\n",
|
||||
"\n",
|
||||
"fig = m1_data.data[\"BAC\"].vbt.ohlcv.plot()\n",
|
||||
"vwapD.vwap.vbt.plot(fig=fig)\n",
|
||||
"#vwapT.vwap.vbt.plot(fig=fig)\n",
|
||||
"fig.show()\n",
|
||||
"\n",
|
||||
"vwapD.vwap\n",
|
||||
"\n",
|
||||
"#vwap = vbt.VWAP.run()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"m1_data.data[\"BAC\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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 = 1\n",
|
||||
"entry_window_closes = 350\n",
|
||||
"\n",
|
||||
"forced_exit_start = 360\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",
|
||||
"long_entries = (rsi.rsi.vbt.crossed_below(28) & entry_window_open)\n",
|
||||
"long_exits = (rsi.rsi.vbt.crossed_above(70) | forced_exit)\n",
|
||||
"#long_entries.info()\n",
|
||||
"#number of trues and falses in long_entries\n",
|
||||
"#long_entries.value_counts()\n",
|
||||
"long_exits.value_counts()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"close"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def plot_rsi(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=True)) \n",
|
||||
" exits.vbt.signals.plot_as_exits(close, fig=fig, add_trace_kwargs=dict(secondary_y=True)) \n",
|
||||
" return fig\n",
|
||||
"\n",
|
||||
"plot_rsi(rsi, close, long_entries, long_exits)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rsi.rsi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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.4/100, 0.05/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, entries=long_entries, exits=long_exits, sl_stop=sl_stop, tp_stop = sl_stop, 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[(0.0003,0.0018)].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
|
||||
}
|
||||
949
research/strat1/strat1_v1_MULTI.ipynb
Normal file
949
research/strat1/strat1_v1_MULTI.ipynb
Normal file
@ -0,0 +1,949 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
265
research/strat1/strat1_v1_SINGLE.ipynb
Normal file
265
research/strat1/strat1_v1_SINGLE.ipynb
Normal file
@ -0,0 +1,265 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"celkovy optimalizacni backtest na vetsim oknu 1 - 300\n",
|
||||
"a možná take to udělat jako parametr\n",
|
||||
"zkusit CV\n",
|
||||
"zobrazit nejak robustnost parametru"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"vbt.settings.returns.year_freq = \"252 days\" \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=\"f1ac6651\", #138170bc 0fb5043a bde6d0be f1ac6651\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",
|
||||
"# 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",
|
||||
"# #basic_data.info()\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": [
|
||||
"# basic_data.stats()\n",
|
||||
"\n",
|
||||
"basic_data.data[\"SPY\"].info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vbt.open_api_ref(vbt.base)\n",
|
||||
"\n",
|
||||
"vbt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"##na toto udelat crosssvalidationu nebo alespon na testovacim ci jinem obdobi\n",
|
||||
"#take udelat long leg - tato je shortovaci\n",
|
||||
"\n",
|
||||
"#8\t-0.06\t-0.2\t0.0028\t0.0048\t4.156254\n",
|
||||
"\n",
|
||||
"#short combination ok for train(4)/test(0.1) (window 1-90, fe 95-100)\n",
|
||||
"#2,\t-0.02,\t-0.25,\t0.0018,\t0.0068\n",
|
||||
"\n",
|
||||
"#dalsi ok hodnota shortu for train/test 4/1\n",
|
||||
"#70,\t8,\t-0.06,\t-0.2,\t0.0013,\t0.0053\t\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#kombinace bez roc_th, train/test 7/-1.5\n",
|
||||
"#70\t7\t-0.07\t0.0033\t0.0063\n",
|
||||
"\n",
|
||||
"#opet bez roc_th, train(5.77)/test 0.9 - spolus tsl_stop + tsl_th\n",
|
||||
"#29\t7\t-0.09\t0.0033\t0.0068\n",
|
||||
"\n",
|
||||
"#bez roc_th a s trailing sl train/test 8.1/-0.8 \n",
|
||||
"#70\t2\t-0.05\t0.0018\t0.0068\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#SPY - short\n",
|
||||
"# entry_window_closes\tmom_timeperiod\tmom_th\tsl_stop\ttp_stop\t\t\t\t\t\n",
|
||||
"# 10\t6\t-0.13\t0.0022\t0.0057\n",
|
||||
"\n",
|
||||
"#5\t7\t-0.19\t0.0037\t0.0042\n",
|
||||
"\n",
|
||||
"#SPY - long\n",
|
||||
"#45\t4\t0.27\t0.0047\t0.0067\n",
|
||||
"\n",
|
||||
"# TODO:\n",
|
||||
"#- vyzkouset zda nejvyhodnejsi kombinace krom train/testu funguje i na nasledujicich dnech po trainu\n",
|
||||
"# -zkusit najit v short datasetu neco vyhodneho co funguji i na testu\n",
|
||||
"# - dodelat kombinace pro long signaly\n",
|
||||
"# - zkusit walk forward\n",
|
||||
"# - vytvorit vysledkove totoznou na v2realbot\n",
|
||||
"# - podivat se jak detailne funguji tsl_stop a tsl_th\n",
|
||||
"\n",
|
||||
"#70,\t4,\t-0.07,\t0.0048,\t0.0068\t\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"entry_window_closes, mom_timeperiod, mom_th, sl_stop, tp_stop = 8,\t3,\t0.07,\t0.0028,\t0.0033\t\n",
|
||||
"roc_th = 0\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",
|
||||
"\n",
|
||||
"long_signal = momshort.real_crossed_above(mom_th)\n",
|
||||
"\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=entries, exits=exits, tsl_stop=sl_stop, tp_stop = tp_stop, fees=0.0167/100, freq=\"1s\") #sl_stop=sl_stop, tp_stop = sl_stop,\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf_B = pf.resample(\"30T\")\n",
|
||||
"\n",
|
||||
"pf_B.stats()\n",
|
||||
"pf_B.orders.records_readable\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.value.plot().show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
932
research/strat_CANDLEGAPS/CANDLEGAPS_v1_MULTI.ipynb
Normal file
932
research/strat_CANDLEGAPS/CANDLEGAPS_v1_MULTI.ipynb
Normal 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
|
||||
}
|
||||
842
research/strat_CANDLEGAPS/CANDLEGAPS_v1_SINGLE.ipynb
Normal file
842
research/strat_CANDLEGAPS/CANDLEGAPS_v1_SINGLE.ipynb
Normal file
@ -0,0 +1,842 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# CANDLEGAPS\n",
|
||||
"\n",
|
||||
"* gaps on second based bars indicates short-term up/down move\n",
|
||||
"\n",
|
||||
"TODO:\n",
|
||||
"* dodělat shorty\n",
|
||||
"* přidat kombinace angle nebo nějaké podobné krátkodobé momentum jako doplňkový indikátor\n",
|
||||
"* vyzkouset ruzne timeframe (sec a min) + hodnotu gapu a dalsi podminky"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"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": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"basic_data.data[\"BAC\"].info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Add resample function to custom columns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"s1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','trades','sellvolume']]\n",
|
||||
"\n",
|
||||
"s2data = s1data.resample(\"2s\")\n",
|
||||
"s2data = s2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\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",
|
||||
"s2close = s2data.close\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)\n",
|
||||
"\n",
|
||||
"resampler_s = vbt.Resampler(s2data.index, s1data.index, source_freq=\"2s\", target_freq=\"1s\")\n",
|
||||
"s2close_realigned = s2close.vbt.realign_closing(resampler_s)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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()\n",
|
||||
"\n",
|
||||
"div_rel = (s1data.close.vbt - t1vwap_h_real) - 1\n",
|
||||
"\n",
|
||||
"div_rel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
" (s2data.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",
|
||||
" left = [\n",
|
||||
" (div_rel, \"reldiv1s_1Hvwap\",)\n",
|
||||
" ]\n",
|
||||
")\n",
|
||||
"ch = chart([pane1], size=\"s\", xloc=slice(\"2024-05-1 09:30:00\",\"2024-05-5 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",
|
||||
"s5low = s5data.data[\"BAC\"].low\n",
|
||||
"s5close_prev = s5close.shift(1)\n",
|
||||
"s5open_prev = s5open.shift(1)\n",
|
||||
"s5high_prev = s5high.shift(1)\n",
|
||||
"s5low_prev = s5low.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) & (s5close > s5open)\n",
|
||||
"\n",
|
||||
"print(entry_ups.value_counts())\n",
|
||||
"\n",
|
||||
"entry_downs = (s5close_prev < s5open_prev) & (s5open < s5low_prev - 0.012) & (s5close < s5close_prev)\n",
|
||||
"\n",
|
||||
"print(entry_downs.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\n",
|
||||
"forced_exit_start = 380\n",
|
||||
"forced_exit_end = 390"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#entry_ups = pd.Series(False, index=s5data.index)\n",
|
||||
"\n",
|
||||
"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_ups = entry_ups & entry_window_open\n",
|
||||
"# entry_ups\n",
|
||||
"\n",
|
||||
"entry_down_window_open= pd.Series(False, index=entry_downs.index)\n",
|
||||
"entry_down_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n",
|
||||
"entry_downs = entry_downs & entry_down_window_open\n",
|
||||
"\n",
|
||||
"forced_exits = pd.Series(False, index=s5data.index)\n",
|
||||
"forced_exits[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n",
|
||||
"\n",
|
||||
"# forced_exits\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"entry_ups.value_counts()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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, entry_downs),\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-05-20 09:30:00\",\"2024-05-25 16:00:00\"), precision=6)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pd.set_option('display.max_rows', None)\n",
|
||||
"# 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, exits=forced_exits, direction=\"longonly\", sl_stop=0.05/100, tp_stop = 0.05/100, fees=0.0167/100, freq=\"5s\")\n",
|
||||
"pf.stats()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.xloc[\"2024-02-20 09:30:00\":\"2024-05-25 16:00:00\"].plot()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vbt.pdir(pf)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.xloc[\"2024-05-20 09:30:00\":\"2024-05-25 16:00:00\"].asset_value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"hourly_returns = pf.returns.resample(\"h\").get()\n",
|
||||
"hourly_returns.plot()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.returns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.value.vbt.lineplot()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf5 = pf.xloc[\"2024-05-20 09:30:00\":\"2024-05-25 16:00:00\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"monthly_returns = pf5.returns_acc.resample(\"5T\").get()\n",
|
||||
"monthly_returns = monthly_returns[monthly_returns!=0]\n",
|
||||
"\n",
|
||||
"monthly_returns\n",
|
||||
"#monthly_returns.vbt.heatmap() \n",
|
||||
"# fig = monthly_returns.vbt.heatmap() \n",
|
||||
"# fig = monthly_returns.vbt.ts_heatmap() "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pd.set_option('display.max_rows', None)\n",
|
||||
"pf.stats()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.plot().save_png()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.trades.records_readable.sort_values(by=\"PnL\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf.xloc[\"2024-03-13 09:30:00\":\"2024-03-20 16:00:00\"].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
|
||||
}
|
||||
949
research/strat_LINREG_MULTI/v1_MULTI.ipynb
Normal file
949
research/strat_LINREG_MULTI/v1_MULTI.ipynb
Normal file
@ -0,0 +1,949 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
584
research/strat_LINREG_MULTI/v1_SINGLE.ipynb
Normal file
584
research/strat_LINREG_MULTI/v1_SINGLE.ipynb
Normal file
@ -0,0 +1,584 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Multi timeframe momentum\n",
|
||||
"Cílen je nalézt kombinaci trendu, kdy je velmi pravdě+podobné, že trend bude o určitou hodnootu ještě pokračovat.\n",
|
||||
"\n",
|
||||
"jsou počítány linregression úhly pro více timeframů a délku oken\n",
|
||||
"\n",
|
||||
"Pro každou kombinaci je daný parametr nad kterým musí být. Pokud je nad všemi pak je entry (short/long).\n",
|
||||
"\n",
|
||||
"Zvážit i nějaký kumulativní počítadlo anglů - něco jako trend kummulátor."
|
||||
]
|
||||
},
|
||||
{
|
||||
"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=\"f1ac6651\", #138170bc 0fb5043a bde6d0be f1ac6651\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",
|
||||
"# 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",
|
||||
"# #basic_data.info()\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 10:30\":\"2024-02-14 12: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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Add resample function to custom columns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
" }\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"basic_data._feature_config = _feature_config"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#asic_data.stats()\n",
|
||||
"basic_data.wrapper.index.normalize().nunique()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1data.data[\"BAC\"].buyvolume"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1data.data[\"BAC\"].sellvolume"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"\n",
|
||||
"order_imbalance_allvolume = cof / t1data.data[\"BAC\"].volume"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"order_imbalance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#priminds list (cena), secinds list (napr. rsi), close, voluminds (volume based)\n",
|
||||
"def plot_2y_close(priminds, secinds, close, volume):\n",
|
||||
" fig = vbt.make_subplots(rows=2, cols=1, shared_xaxes=True, \n",
|
||||
" specs=[[{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n",
|
||||
" vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n",
|
||||
"\n",
|
||||
" # Plotting the close price\n",
|
||||
" close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False,row=1, col=1), trace_kwargs=dict(line=dict(color=\"blue\")))\n",
|
||||
" \n",
|
||||
" # Plotting primary indicators on the first row\n",
|
||||
" for ind in priminds:\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
" \n",
|
||||
" # Plotting secondary indicators on the first row\n",
|
||||
" for ind in secinds:\n",
|
||||
" #ind = ind.rename(str(ind.name))\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n",
|
||||
" \n",
|
||||
" for indvolume in volume:\n",
|
||||
" # Plotting the volume on the second row\n",
|
||||
" indvolume.rename(str(indvolume.name)).vbt.barplot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n",
|
||||
" #vbt.Bar(indvolume, fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n",
|
||||
" \n",
|
||||
" return fig\n",
|
||||
"\n",
|
||||
"plot_2y_close([], [cof,oibratio], t1data.close, [t1data.data[\"BAC\"].buyvolume, t1data.data[\"BAC\"].sellvolume, t1data.volume])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"t0data = basic_data\n",
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"1T\")\n",
|
||||
"t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"15T\")\n",
|
||||
"t3data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"30T\")\n",
|
||||
"t4data = basic_data[['open', 'high', 'low', 'close', 'volume', 'vwap']].resample(\"D\").dropna()\n",
|
||||
"\n",
|
||||
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"t3data = t3data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"\n",
|
||||
"#30min data to daily\n",
|
||||
"# t4data = t3data.resample(\"D\").dropna()\n",
|
||||
"\n",
|
||||
"#t4data = t4data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"#m1data.data[\"SPY\"].info()\n",
|
||||
"\n",
|
||||
"#m1data.data[\"SPY\"].vbt.ohlcv.plot()\n",
|
||||
"#h2data.data[\"SPY\"].vbt.ohlcv.plot()\n",
|
||||
"#ddata.data[\"SPY\"]\n",
|
||||
"t2data.data[\"BAC\"].vbt.ohlcv.plot().show()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#t4data.data[\"BAC\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t2data.close\n",
|
||||
"\n",
|
||||
"#in df remove rows with nan\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#realign na 1T = t1data + oriznout main session\n",
|
||||
"t2data_vwap = t2data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"t3data_vwap = t3data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"t4data_vwap = t4data.vwap.vbt.realign_closing(\"1T\").dropna()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t2data_vwap"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"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",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
|
||||
" for ind in secinds:\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))\n",
|
||||
" return fig"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t4data.clos.vbt \n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"obvind = vbt.indicator.obv.run(t1data.close, t1data.volume)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1_lengtgh = 15\n",
|
||||
"t2_length = 15\n",
|
||||
"t3_length = 15\n",
|
||||
"t4_length = 5\n",
|
||||
"t1_th = 0.1\n",
|
||||
"t2_th = 0.1\n",
|
||||
"t3_th = 0.1\n",
|
||||
"t4_th = 0.1\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#minute\n",
|
||||
"t1slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t1data.close, timeperiod=t1_lengtgh) # -0.09, 0.09\n",
|
||||
"t2slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t2data.vwap, timeperiod=t2_length) # -0.08 , 0.079\n",
|
||||
"t3slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t3data.vwap, timeperiod=t3_length) # -0.08, 0.08\n",
|
||||
"#daily\n",
|
||||
"t4slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t4data.vwap, timeperiod=t4_length) # -0.1, 0.09\n",
|
||||
"\n",
|
||||
"plot_2y_close(priminds=[], secinds=[t1slope, t2slope, t3slope, t4slope], close=t1data.close).show()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#thirtymin_slope = thirtymin_slope.real.rename(\"30min\") #timto se prejmenuje real na 30min\n",
|
||||
"t3slope = t3slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"##filter daily_slope_to_compare to only monday to friday\n",
|
||||
"t3slope = t3slope[t3slope.index.dayofweek < 5]\n",
|
||||
"\n",
|
||||
"#t3slope.info()\n",
|
||||
"\n",
|
||||
"t2slope = t2slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"##filter daily_slope_to_compare to only monday to friday\n",
|
||||
"t2slope = t2slope[t2slope.index.dayofweek < 5]\n",
|
||||
"\n",
|
||||
"t2slope.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"oibratio"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"#\n",
|
||||
"short_entries = order_imbalance.vbt < 0.0002\n",
|
||||
"#short_entries = oibratio.vbt < 0.01\n",
|
||||
"short_entries.value_counts()\n",
|
||||
"\n",
|
||||
"entries = order_imbalance.vbt > 0.7\n",
|
||||
"#entries = oibratio.vbt > 10\n",
|
||||
"entries.value_counts()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig = vbt.make_subplots(rows=3, cols=1, shared_xaxes=True, \n",
|
||||
" specs=[[{\"secondary_y\": True}], [{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n",
|
||||
" vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n",
|
||||
"t1data.data[\"BAC\"].vbt.ohlcv.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
"#oibratio.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n",
|
||||
"order_imbalance.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n",
|
||||
"entries.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",
|
||||
" ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
"\n",
|
||||
"short_entries.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"SHORTS\",\n",
|
||||
" line=dict(color=\"#ffe476\"),\n",
|
||||
" marker=dict(color=\"red\"),\n",
|
||||
" fill=None,\n",
|
||||
" connectgaps=True,\n",
|
||||
" ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# thirtymin_slope_to_compare.vbt.xloc[\"04-16-2024\"].get()\n",
|
||||
"thirty_down_signal.vbt.xloc[\"04-16-2024\"].get()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"# 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
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
932
research/strat_ORDER_IMBALANCE/v1_MULTI.ipynb
Normal file
932
research/strat_ORDER_IMBALANCE/v1_MULTI.ipynb
Normal 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
|
||||
}
|
||||
964
research/strat_ORDER_IMBALANCE/v1_SINGLE.ipynb
Normal file
964
research/strat_ORDER_IMBALANCE/v1_SINGLE.ipynb
Normal file
@ -0,0 +1,964 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# ORDER Imbalance\n",
|
||||
"\n",
|
||||
"* introduced buyvolume and sellvolume on bar level.\n",
|
||||
"* calculated order imbalance ratio (buyvolume-sellvolume/totalvolume)\n",
|
||||
"* calculated on multiple timeframes\n",
|
||||
"* entry based on confluences imbalances\n",
|
||||
"\n",
|
||||
"## Note\n",
|
||||
"\n",
|
||||
"Order disbalance nepodminuje zmenu ceny (tzn. muze byt order disbalance na buy stranu, ale cena nemusi jit nahoru a naopak)\n",
|
||||
"Nicmene pokud je disbalance delsi a nedochazi ke zmene ceny - může to něco indikovat. \n",
|
||||
"Vytvořit si kumulativní disbalance - kumulátory, které se budou načítat, když se budou silné disbalance, bez změny ceny. Tento akumulátor se bude nabíjet disbalancí a vybíjet příslušnou změnou ceny."
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"from lightweight_charts import JupyterChart, chart as chartp, Panel\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\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-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-03-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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Add resample function to custom columns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
" }\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"basic_data._feature_config = _feature_config"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#asic_data.stats()\n",
|
||||
"basic_data.wrapper.index.normalize().nunique()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#basic_data.ohlcv.plot()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"second_data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']]\n",
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"#t1data = t1data.xloc[\"2024-02-12 9:30\":\"2024-02-14 16:00\"]\n",
|
||||
"basic_data = t1data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"##z tohoto si udelat plot funkci (i pro entries,exits)\n",
|
||||
"#t1data = t1data[[\"open\", \"high\", \"low\", \"close\", \"volume\"]]\n",
|
||||
"chart = JupyterChart(width=1000, height=600, inner_width=1, inner_height=0.5, leftScale=True)\n",
|
||||
"#set resolution\n",
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")\n",
|
||||
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"chart.set(t1data.data[\"BAC\"])\n",
|
||||
"line_vwap = chart.create_line(name=\"vwap\")#, color=\"blue\")\n",
|
||||
"line_vwap.set(t1data.vwap)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"chart.topbar.textbox(\"title\",\"Nadpis\")\n",
|
||||
"chart2 = chart.create_subchart(position='right', width=1, height=0.5, sync=True, leftScale=True)\n",
|
||||
"t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"5T\")\n",
|
||||
"t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#5min close realigned to 1T\n",
|
||||
"close_realigned = t2data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n",
|
||||
"#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n",
|
||||
"line1 = chart.create_line(name=\"5minclose\")#, color=\"green\")\n",
|
||||
"line1.set(close_realigned)\n",
|
||||
"\n",
|
||||
"#sma z realigned dat\n",
|
||||
"sma_tp = 20\n",
|
||||
"sma_t2 = vbt.indicator(\"talib:EMA\").run(close_realigned, timeperiod=sma_tp)\n",
|
||||
"smaline = chart.create_line(name=f\"sma{sma_tp}\")#, color=\"blue\")\n",
|
||||
"smaline.set(sma_t2)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#sma z puvodnich resamplovanych dat plus navic realign, melo by byt stejne \n",
|
||||
"sma_real = vbt.indicator(\"talib:EMA\").run(t2data.close, timeperiod=sma_tp)\n",
|
||||
"sma_real_value = sma_real.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"sma_real_value = sma_real_value[sma_real_value.index.dayofweek < 5]\n",
|
||||
"smaline_real = chart.create_line(name=f\"smareal{sma_tp}\", color=\"yellow\")\n",
|
||||
"smaline_real.set(sma_real_value)\n",
|
||||
"\n",
|
||||
"#resample 15T\n",
|
||||
"t15data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"15T\")\n",
|
||||
"t15data = t15data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"\n",
|
||||
"#5min close realigned to 1T\n",
|
||||
"close_15realigned = t15data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"close_15realigned = close_15realigned[close_15realigned.index.dayofweek < 5]\n",
|
||||
"#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n",
|
||||
"line2 = chart.create_line(name=\"15minclose\")#, color=\"pink\")\n",
|
||||
"line2.set(close_15realigned)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"chart.legend(True)\n",
|
||||
"hst = chart2.create_histogram(name=\"buyvolume\", color=\"rgba(53, 94, 59, 0.6)\") #green transparent\n",
|
||||
"hst1 = chart2.create_histogram(name=\"sellvolume\", color=\"rgba(165, 42, 42, 0.6)\") #red transparent\n",
|
||||
"hst.set(t1data.data[\"BAC\"])\n",
|
||||
"hst1.set(t1data.data[\"BAC\"])\n",
|
||||
"line2 = chart2.create_line(name=\"5minclose\")#, color=\"green\")\n",
|
||||
"line2.set(close_realigned)\n",
|
||||
"\n",
|
||||
"lineoib = chart2.create_line(name=\"oib\", priceScaleId=\"left\") #color=\"violet\", \n",
|
||||
"#lineoib.scale(0.7,0)\n",
|
||||
"lineoib.set(order_imbalance_allvolume)\n",
|
||||
"\n",
|
||||
"lineoib_sma = chart2.create_line(name=\"oibsma5\", priceScaleId=\"left\") #, color=\"blue\", \n",
|
||||
"lineoib_sma.set(order_imbalance_sma)\n",
|
||||
"\n",
|
||||
"chart.fit()\n",
|
||||
"chart2.legend(True)\n",
|
||||
"#\n",
|
||||
"line2.markers_set(short_signals, \"entries\")\n",
|
||||
"# TODO jelikoz se davaji do jednoho pole je treba zajistit spravne sortovani\n",
|
||||
"# domyslet jak to pojmout iterativni doplnovani markeru\n",
|
||||
"line2.markers_set(short_exits, \"exits\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"chart2.fit()\n",
|
||||
"chart.load()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"short_signals.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#vbt.IF.list_indicators(\"*ma\")\n",
|
||||
"vbt.phelp(vbt.indicator(\"talib:EMA\").run)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sma = vbt.indicator(\"talib:EMA\").run(t1data.close, timeperiod=20)\n",
|
||||
"sma.real.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rr = vbt.RSI.run(t1data.close)\n",
|
||||
"type(rr)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"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\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"short_signals.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"short_signals"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"order_imbalance.fillna(0)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"order_imbalance.vbt.plot()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"order_imbalance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"chartN = JupyterChart(width=500, height=300, inner_width=1, inner_height=0.3, leftScale=True)\n",
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")\n",
|
||||
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"chartN.set(t1data.data[\"BAC\"])\n",
|
||||
"line_sma = chartN.create_line(name=\"sma\", priceScaleId=\"right\")#, color=\"blue\")\n",
|
||||
"line_sma.set(sma)\n",
|
||||
"# line_sma.markers_set(short_signals, \"entries\")\n",
|
||||
"# line_sma.markers_set(short_exits, \"exits\")\n",
|
||||
"# hst = chartN.create_histogram(name=\"oivol\")\n",
|
||||
"# hst.set(order_imbalance_allvolume)\n",
|
||||
"# chartN.legend(True)\n",
|
||||
"# chartN.fit()\n",
|
||||
"\n",
|
||||
"# subchart = chartN.create_subchart(position='right', width=1, height=0.5, sync=False, leftScale=True)\n",
|
||||
"# # subchart.set(t1data.data[\"BAC\"])\n",
|
||||
"# line_sma1 = subchart.create_line(name=\"smao\", priceScaleId=\"left\")#, color=\"blue\")\n",
|
||||
"# line_sma1.set(sma)\n",
|
||||
"# # line_sma1.markers_set(short_signals, \"entries\")\n",
|
||||
"# # line_sma1.markers_set(short_exits, \"exits\")\n",
|
||||
"# hsto = subchart.create_histogram(name=\"oivolo\")\n",
|
||||
"# hsto.set(order_imbalance_sma)\n",
|
||||
"\n",
|
||||
"chart2 = chartN.create_subchart(position='left', width=1, height=0.5, sync=True, leftScale=True, toolbox=True)\n",
|
||||
"# hst = chart2.create_histogram(name=\"buyvolume\", color=\"rgba(53, 94, 59, 0.6)\") #green transparent\n",
|
||||
"# hst1 = chart2.create_histogram(name=\"sellvolume\", color=\"rgba(165, 42, 42, 0.6)\") #red transparent\n",
|
||||
"# hst.set(t1data.data[\"BAC\"])\n",
|
||||
"# hst1.set(t1data.data[\"BAC\"])\n",
|
||||
"line2 = chart2.create_line(name=\"sma\")#, color=\"green\")\n",
|
||||
"line2.set(sma)\n",
|
||||
"chart2.topbar.textbox(\"title\",\"Nadpis\")\n",
|
||||
"# chartN.topbar.textbox(\"title\",\"NadpisT\")\n",
|
||||
"\n",
|
||||
"# subchart.legend(True)\n",
|
||||
"# subchart.fit()\n",
|
||||
"chartN.load()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"##z tohoto si udelat plot funkci (i pro entries,exits)\n",
|
||||
"#t1data = t1data[[\"open\", \"high\", \"low\", \"close\", \"volume\"]]\n",
|
||||
"chart = JupyterChart(width=1000, height=600, inner_width=1, inner_height=0.5, leftScale=True)\n",
|
||||
"#set resolution\n",
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")\n",
|
||||
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"chart.set(t1data.data[\"BAC\"])\n",
|
||||
"line_vwap = chart.create_line(name=\"vwap\")#, color=\"blue\")\n",
|
||||
"line_vwap.set(t1data.vwap)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"chart.topbar.textbox(\"title\",\"Nadpis\")\n",
|
||||
"chart2 = chart.create_subchart(position='right', width=1, height=0.5, sync=True, leftScale=True)\n",
|
||||
"t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"5T\")\n",
|
||||
"t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#5min close realigned to 1T\n",
|
||||
"close_realigned = t2data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n",
|
||||
"#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n",
|
||||
"line1 = chart.create_line(name=\"5minclose\")#, color=\"green\")\n",
|
||||
"line1.set(close_realigned)\n",
|
||||
"\n",
|
||||
"#sma z realigned dat\n",
|
||||
"sma_tp = 20\n",
|
||||
"sma_t2 = vbt.indicator(\"talib:EMA\").run(close_realigned, timeperiod=sma_tp)\n",
|
||||
"smaline = chart.create_line(name=f\"sma{sma_tp}\")#, color=\"blue\")\n",
|
||||
"smaline.set(sma_t2)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#sma z puvodnich resamplovanych dat plus navic realign, melo by byt stejne \n",
|
||||
"sma_real = vbt.indicator(\"talib:EMA\").run(t2data.close, timeperiod=sma_tp)\n",
|
||||
"sma_real_value = sma_real.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"sma_real_value = sma_real_value[sma_real_value.index.dayofweek < 5]\n",
|
||||
"smaline_real = chart.create_line(name=f\"smareal{sma_tp}\", color=\"yellow\")\n",
|
||||
"smaline_real.set(sma_real_value)\n",
|
||||
"\n",
|
||||
"#resample 15T\n",
|
||||
"t15data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"15T\")\n",
|
||||
"t15data = t15data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"\n",
|
||||
"#5min close realigned to 1T\n",
|
||||
"close_15realigned = t15data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"close_15realigned = close_15realigned[close_15realigned.index.dayofweek < 5]\n",
|
||||
"#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n",
|
||||
"line2 = chart.create_line(name=\"15minclose\")#, color=\"pink\")\n",
|
||||
"line2.set(close_15realigned)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"chart.legend(True)\n",
|
||||
"hst = chart2.create_histogram(name=\"buyvolume\", color=\"rgba(53, 94, 59, 0.6)\") #green transparent\n",
|
||||
"hst1 = chart2.create_histogram(name=\"sellvolume\", color=\"rgba(165, 42, 42, 0.6)\") #red transparent\n",
|
||||
"hst.set(t1data.data[\"BAC\"])\n",
|
||||
"hst1.set(t1data.data[\"BAC\"])\n",
|
||||
"line2 = chart2.create_line(name=\"5minclose\")#, color=\"green\")\n",
|
||||
"line2.set(close_realigned)\n",
|
||||
"\n",
|
||||
"lineoib = chart2.create_line(name=\"oib\", priceScaleId=\"left\") #color=\"violet\", \n",
|
||||
"#lineoib.scale(0.7,0)\n",
|
||||
"lineoib.set(order_imbalance_allvolume)\n",
|
||||
"\n",
|
||||
"lineoib_sma = chart2.create_line(name=\"oibsma5\", priceScaleId=\"left\") #, color=\"blue\", \n",
|
||||
"lineoib_sma.set(order_imbalance_sma)\n",
|
||||
"\n",
|
||||
"chart.fit()\n",
|
||||
"chart2.legend(True)\n",
|
||||
"#\n",
|
||||
"line2.markers_set(short_signals, \"entries\")\n",
|
||||
"# TODO jelikoz se davaji do jednoho pole je treba zajistit spravne sortovani\n",
|
||||
"# domyslet jak to pojmout iterativni doplnovani markeru\n",
|
||||
"line2.markers_set(short_exits, \"exits\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"chart2.fit()\n",
|
||||
"chart.load()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sma.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#priminds list (same Y as price), secinds list (secondary Y napr. rsi), close, voluminds (volume based) list\n",
|
||||
"def plot_2y_close(priminds, secinds, close, volumeinds, ohlcv=None):\n",
|
||||
" fig = vbt.make_subplots(rows=2, cols=1, shared_xaxes=True, \n",
|
||||
" specs=[[{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n",
|
||||
" vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n",
|
||||
"\n",
|
||||
" if ohlcv is not None:\n",
|
||||
" ohlcv.vbt.ohlcv.plot(fig=fig, add_trace_kwargs=dict(row=1, col=1))\n",
|
||||
"\n",
|
||||
" # Plotting the close price\n",
|
||||
" close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False,row=1, col=1), trace_kwargs=dict(line=dict(color=\"blue\")))\n",
|
||||
" \n",
|
||||
" # Plotting primary indicators on the first row\n",
|
||||
" for ind in priminds:\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" #if series has no name, make the name same as the variable name\n",
|
||||
" \n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
" \n",
|
||||
" # Plotting secondary indicators on the first row\n",
|
||||
" for ind in secinds:\n",
|
||||
" #ind = ind.rename(str(ind.name))\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1), trace_kwargs=dict(line=dict(color=\"rgba(255, 0, 0, 0.4)\")))\n",
|
||||
" \n",
|
||||
" for indvolume in volumeinds:\n",
|
||||
" # Plotting the volume on the second row\n",
|
||||
" indvolume.rename(str(indvolume.name)).vbt.barplot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n",
|
||||
" #vbt.Bar(indvolume, fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n",
|
||||
" \n",
|
||||
" return fig\n",
|
||||
"\n",
|
||||
"fig = plot_2y_close([sma], [order_imbalance.rename(\"order_imbalance_norm\"),order_imbalance_sma.real.rename(\"oib_sma\")], t1data.close, [t1data.data[\"BAC\"].buyvolume, t1data.data[\"BAC\"].sellvolume, t1data.volume], t1data.data[\"BAC\"])\n",
|
||||
"fig.update_yaxes(range=[33,34], secondary_y=False, row=1, col=1) #update y axis range\n",
|
||||
"fig.update_yaxes(range=[-1,1], secondary_y=True, row=1, col=1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"t0data = basic_data\n",
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"1T\")\n",
|
||||
"t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"15T\")\n",
|
||||
"t3data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"30T\")\n",
|
||||
"t4data = basic_data[['open', 'high', 'low', 'close', 'volume', 'vwap']].resample(\"D\").dropna()\n",
|
||||
"\n",
|
||||
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"t3data = t3data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"\n",
|
||||
"#30min data to daily\n",
|
||||
"# t4data = t3data.resample(\"D\").dropna()\n",
|
||||
"\n",
|
||||
"#t4data = t4data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"#m1data.data[\"SPY\"].info()\n",
|
||||
"\n",
|
||||
"#m1data.data[\"SPY\"].vbt.ohlcv.plot()\n",
|
||||
"#h2data.data[\"SPY\"].vbt.ohlcv.plot()\n",
|
||||
"#ddata.data[\"SPY\"]\n",
|
||||
"t2data.data[\"BAC\"].vbt.ohlcv.plot().show()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#t4data.data[\"BAC\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t2data.close\n",
|
||||
"\n",
|
||||
"#in df remove rows with nan\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#realign na 1T = t1data + oriznout main session\n",
|
||||
"t2data_vwap = t2data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"t3data_vwap = t3data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"t4data_vwap = t4data.vwap.vbt.realign_closing(\"1T\").dropna()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t2data_vwap"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"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",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
|
||||
" for ind in secinds:\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))\n",
|
||||
" return fig"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t4data.clos.vbt \n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"obvind = vbt.indicator.obv.run(t1data.close, t1data.volume)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1_lengtgh = 15\n",
|
||||
"t2_length = 15\n",
|
||||
"t3_length = 15\n",
|
||||
"t4_length = 5\n",
|
||||
"t1_th = 0.1\n",
|
||||
"t2_th = 0.1\n",
|
||||
"t3_th = 0.1\n",
|
||||
"t4_th = 0.1\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#minute\n",
|
||||
"t1slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t1data.close, timeperiod=t1_lengtgh) # -0.09, 0.09\n",
|
||||
"t2slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t2data.vwap, timeperiod=t2_length) # -0.08 , 0.079\n",
|
||||
"t3slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t3data.vwap, timeperiod=t3_length) # -0.08, 0.08\n",
|
||||
"#daily\n",
|
||||
"t4slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t4data.vwap, timeperiod=t4_length) # -0.1, 0.09\n",
|
||||
"\n",
|
||||
"plot_2y_close(priminds=[], secinds=[t1slope, t2slope, t3slope, t4slope], close=t1data.close).show()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#thirtymin_slope = thirtymin_slope.real.rename(\"30min\") #timto se prejmenuje real na 30min\n",
|
||||
"t3slope = t3slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"##filter daily_slope_to_compare to only monday to friday\n",
|
||||
"t3slope = t3slope[t3slope.index.dayofweek < 5]\n",
|
||||
"\n",
|
||||
"#t3slope.info()\n",
|
||||
"\n",
|
||||
"t2slope = t2slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"##filter daily_slope_to_compare to only monday to friday\n",
|
||||
"t2slope = t2slope[t2slope.index.dayofweek < 5]\n",
|
||||
"\n",
|
||||
"t2slope.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"oibratio"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"#\n",
|
||||
"short_signals = order_imbalance.vbt < -0.3\n",
|
||||
"#short_entries = oibratio.vbt < 0.01\n",
|
||||
"short_signals.value_counts()\n",
|
||||
"\n",
|
||||
"long_signals = order_imbalance.vbt > 0.3\n",
|
||||
"#entries = oibratio.vbt > 10\n",
|
||||
"long_signals.value_counts()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig = vbt.make_subplots(rows=3, cols=1, shared_xaxes=True, \n",
|
||||
" specs=[[{\"secondary_y\": True}], [{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n",
|
||||
" vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n",
|
||||
"t1data.data[\"BAC\"].vbt.ohlcv.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
"#oibratio.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n",
|
||||
"order_imbalance.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n",
|
||||
"long_signals.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",
|
||||
" ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
"\n",
|
||||
"short_signals.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"SHORTS\",\n",
|
||||
" line=dict(color=\"#ffe476\"),\n",
|
||||
" marker=dict(color=\"red\"),\n",
|
||||
" fill=None,\n",
|
||||
" connectgaps=True,\n",
|
||||
" ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# thirtymin_slope_to_compare.vbt.xloc[\"04-16-2024\"].get()\n",
|
||||
"thirty_down_signal.vbt.xloc[\"04-16-2024\"].get()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
}
|
||||
1411
research/strat_ORDER_IMBALANCE/v2_SINGLE.ipynb
Normal file
1411
research/strat_ORDER_IMBALANCE/v2_SINGLE.ipynb
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
932
research/strat_SUPERTREND/SUPERTREND_v1_MULTI.ipynb
Normal file
932
research/strat_SUPERTREND/SUPERTREND_v1_MULTI.ipynb
Normal 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
|
||||
}
|
||||
679
research/strat_SUPERTREND/SUPERTREND_v1_SINGLE.ipynb
Normal file
679
research/strat_SUPERTREND/SUPERTREND_v1_SINGLE.ipynb
Normal file
@ -0,0 +1,679 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# SUPERTREND\n",
|
||||
"\n",
|
||||
"* kombinace supertrendu na vice urovnich"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"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": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"basic_data.data[\"BAC\"].info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Add resample function to custom columns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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": null,
|
||||
"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": 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
|
||||
}
|
||||
932
research/strat_TIME_ENTRIES copy/v1_MULTI.ipynb
Normal file
932
research/strat_TIME_ENTRIES copy/v1_MULTI.ipynb
Normal 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
|
||||
}
|
||||
595
research/strat_TIME_ENTRIES copy/v1_SINGLE.ipynb
Normal file
595
research/strat_TIME_ENTRIES copy/v1_SINGLE.ipynb
Normal file
@ -0,0 +1,595 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TIME based entries, exits\n",
|
||||
"\n",
|
||||
"Recurring time bases entries and exits"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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-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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Add resample function to custom columns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
" }\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"basic_data._feature_config = _feature_config"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#asic_data.stats()\n",
|
||||
"basic_data.wrapper.index.normalize().nunique()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"basic_data.ohlcv.plot()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1data = t1data.xloc[\"2024-02-12 9:30\":\"2024-02-12 10:20\"]\n",
|
||||
"#t1data = t1data.transform(lambda df: df.between_time('09:30', '10:00').dropna())\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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.fillna(0) #nan nahradime 0\n",
|
||||
"\n",
|
||||
"order_imbalance_allvolume = cof / t1data.data[\"BAC\"].volume"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"cof\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"order_imbalance.vbt.plot()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"order_imbalance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#priminds list (same Y as price), secinds list (secondary Y napr. rsi), close, voluminds (volume based) list\n",
|
||||
"def plot_2y_close(priminds, secinds, close, volumeinds):\n",
|
||||
" fig = vbt.make_subplots(rows=2, cols=1, shared_xaxes=True, \n",
|
||||
" specs=[[{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n",
|
||||
" vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n",
|
||||
"\n",
|
||||
" # Plotting the close price\n",
|
||||
" close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False,row=1, col=1), trace_kwargs=dict(line=dict(color=\"blue\")))\n",
|
||||
" \n",
|
||||
" # Plotting primary indicators on the first row\n",
|
||||
" for ind in priminds:\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" #if series has no name, make the name same as the variable name\n",
|
||||
" \n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
" \n",
|
||||
" # Plotting secondary indicators on the first row\n",
|
||||
" for ind in secinds:\n",
|
||||
" #ind = ind.rename(str(ind.name))\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1), trace_kwargs=dict(line=dict(color=\"rgba(255, 0, 0, 0.4)\")))\n",
|
||||
" \n",
|
||||
" for indvolume in volumeinds:\n",
|
||||
" # Plotting the volume on the second row\n",
|
||||
" indvolume.rename(str(indvolume.name)).vbt.barplot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n",
|
||||
" #vbt.Bar(indvolume, fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n",
|
||||
" \n",
|
||||
" return fig\n",
|
||||
"\n",
|
||||
"plot_2y_close([], [order_imbalance.rename(\"order_imbalance_norm\")], t1data.close, [t1data.data[\"BAC\"].buyvolume, t1data.data[\"BAC\"].sellvolume, t1data.volume])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"t0data = basic_data\n",
|
||||
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"1T\")\n",
|
||||
"t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"15T\")\n",
|
||||
"t3data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"30T\")\n",
|
||||
"t4data = basic_data[['open', 'high', 'low', 'close', 'volume', 'vwap']].resample(\"D\").dropna()\n",
|
||||
"\n",
|
||||
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"t3data = t3data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"\n",
|
||||
"#30min data to daily\n",
|
||||
"# t4data = t3data.resample(\"D\").dropna()\n",
|
||||
"\n",
|
||||
"#t4data = t4data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
||||
"#m1data.data[\"SPY\"].info()\n",
|
||||
"\n",
|
||||
"#m1data.data[\"SPY\"].vbt.ohlcv.plot()\n",
|
||||
"#h2data.data[\"SPY\"].vbt.ohlcv.plot()\n",
|
||||
"#ddata.data[\"SPY\"]\n",
|
||||
"t2data.data[\"BAC\"].vbt.ohlcv.plot().show()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#t4data.data[\"BAC\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t2data.close\n",
|
||||
"\n",
|
||||
"#in df remove rows with nan\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#realign na 1T = t1data + oriznout main session\n",
|
||||
"t2data_vwap = t2data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"t3data_vwap = t3data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"t4data_vwap = t4data.vwap.vbt.realign_closing(\"1T\").dropna()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t2data_vwap"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"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",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))\n",
|
||||
" for ind in secinds:\n",
|
||||
" if isinstance(ind, pd.Series):\n",
|
||||
" ind = ind.vbt\n",
|
||||
" ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))\n",
|
||||
" return fig"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t4data.clos.vbt \n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"obvind = vbt.indicator.obv.run(t1data.close, t1data.volume)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"t1_lengtgh = 15\n",
|
||||
"t2_length = 15\n",
|
||||
"t3_length = 15\n",
|
||||
"t4_length = 5\n",
|
||||
"t1_th = 0.1\n",
|
||||
"t2_th = 0.1\n",
|
||||
"t3_th = 0.1\n",
|
||||
"t4_th = 0.1\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#minute\n",
|
||||
"t1slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t1data.close, timeperiod=t1_lengtgh) # -0.09, 0.09\n",
|
||||
"t2slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t2data.vwap, timeperiod=t2_length) # -0.08 , 0.079\n",
|
||||
"t3slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t3data.vwap, timeperiod=t3_length) # -0.08, 0.08\n",
|
||||
"#daily\n",
|
||||
"t4slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t4data.vwap, timeperiod=t4_length) # -0.1, 0.09\n",
|
||||
"\n",
|
||||
"plot_2y_close(priminds=[], secinds=[t1slope, t2slope, t3slope, t4slope], close=t1data.close).show()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#thirtymin_slope = thirtymin_slope.real.rename(\"30min\") #timto se prejmenuje real na 30min\n",
|
||||
"t3slope = t3slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"##filter daily_slope_to_compare to only monday to friday\n",
|
||||
"t3slope = t3slope[t3slope.index.dayofweek < 5]\n",
|
||||
"\n",
|
||||
"#t3slope.info()\n",
|
||||
"\n",
|
||||
"t2slope = t2slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n",
|
||||
"##filter daily_slope_to_compare to only monday to friday\n",
|
||||
"t2slope = t2slope[t2slope.index.dayofweek < 5]\n",
|
||||
"\n",
|
||||
"t2slope.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"oibratio"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"#\n",
|
||||
"short_entries = order_imbalance.vbt < 0.0002\n",
|
||||
"#short_entries = oibratio.vbt < 0.01\n",
|
||||
"short_entries.value_counts()\n",
|
||||
"\n",
|
||||
"entries = order_imbalance.vbt > 0.7\n",
|
||||
"#entries = oibratio.vbt > 10\n",
|
||||
"entries.value_counts()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig = vbt.make_subplots(rows=3, cols=1, shared_xaxes=True, \n",
|
||||
" specs=[[{\"secondary_y\": True}], [{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n",
|
||||
" vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n",
|
||||
"t1data.data[\"BAC\"].vbt.ohlcv.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
"#oibratio.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n",
|
||||
"order_imbalance.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n",
|
||||
"entries.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",
|
||||
" ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n",
|
||||
"\n",
|
||||
"short_entries.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"SHORTS\",\n",
|
||||
" line=dict(color=\"#ffe476\"),\n",
|
||||
" marker=dict(color=\"red\"),\n",
|
||||
" fill=None,\n",
|
||||
" connectgaps=True,\n",
|
||||
" ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# thirtymin_slope_to_compare.vbt.xloc[\"04-16-2024\"].get()\n",
|
||||
"thirty_down_signal.vbt.xloc[\"04-16-2024\"].get()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
"# 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
|
||||
}
|
||||
161
research/test.ipynb
Normal file
161
research/test.ipynb
Normal file
@ -0,0 +1,161 @@
|
||||
{
|
||||
"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",
|
||||
"\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",
|
||||
"res, df = load_batch(batch_id=\"e44a5075\",\n",
|
||||
" space_resolution_evenly=False,\n",
|
||||
" indicators_columns=[\"Rsi14\"],\n",
|
||||
" main_session_only=True)\n",
|
||||
"if res < 0:\n",
|
||||
" print(\"Error\" + str(res) + str(df))\n",
|
||||
"df = df[\"bars\"]\n",
|
||||
"\n",
|
||||
"#df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# filter dates"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#naloadujeme do vbt symbol as column\n",
|
||||
"basic_data = vbt.Data.from_data({\"BAC\": df}, tz_convert=zoneNY)\n",
|
||||
"start_date = pd.Timestamp('2024-03-12 09:30', tz=zoneNY)\n",
|
||||
"end_date = pd.Timestamp('2024-03-13 16:00', tz=zoneNY)\n",
|
||||
"\n",
|
||||
"#basic_data = basic_data.transform(lambda df: df[df.index.date == start_date.date()])\n",
|
||||
"basic_data = basic_data.transform(lambda df: df[(df.index >= start_date) & (df.index <= end_date)])\n",
|
||||
"#basic_data.data[\"BAC\"].info()\n",
|
||||
"\n",
|
||||
"# fig = basic_data.plot(plot_volume=False)\n",
|
||||
"# pivot_info = basic_data.run(\"pivotinfo\", up_th=0.003, down_th=0.002)\n",
|
||||
"# #pivot_info.plot()\n",
|
||||
"# pivot_info.plot(fig=fig, conf_value_trace_kwargs=dict(visible=True))\n",
|
||||
"# fig.show()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# rsi14 = basic_data.data[\"BAC\"][\"Rsi14\"].rename(\"Rsi14\")\n",
|
||||
"\n",
|
||||
"# rsi14.vbt.plot().show()\n",
|
||||
"# basic_data.data[\"BAC\"].vbt.ohlcv.plot().show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
}
|
||||
82
research/test1.ipynb
Normal file
82
research/test1.ipynb
Normal file
@ -0,0 +1,82 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"import numpy as np\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import statsmodels.api as sm\n",
|
||||
"\n",
|
||||
"# Example time series data\n",
|
||||
"np.random.seed(0)\n",
|
||||
"dates = pd.date_range('2023-01-01', periods=100)\n",
|
||||
"data = pd.Series(np.random.randn(100).cumsum(), index=dates)\n",
|
||||
"\n",
|
||||
"# Parameters\n",
|
||||
"window_size = 20\n",
|
||||
"\n",
|
||||
"# Function to calculate rolling window linear regression\n",
|
||||
"def rolling_linreg(series, window):\n",
|
||||
" intercepts = []\n",
|
||||
" slopes = []\n",
|
||||
" for i in range(len(series) - window + 1):\n",
|
||||
" y = series[i:i + window]\n",
|
||||
" x = np.arange(window)\n",
|
||||
" x = sm.add_constant(x)\n",
|
||||
" model = sm.OLS(y, x).fit()\n",
|
||||
" intercepts.append(model.params[0])\n",
|
||||
" slopes.append(model.params[1])\n",
|
||||
" return intercepts, slopes\n",
|
||||
"\n",
|
||||
"# Calculate rolling linear regression parameters\n",
|
||||
"intercepts, slopes = rolling_linreg(data, window_size)\n",
|
||||
"\n",
|
||||
"# Create a DataFrame for plotting\n",
|
||||
"rolling_dates = dates[window_size - 1:]\n",
|
||||
"rolling_intercepts = pd.Series(intercepts, index=rolling_dates)\n",
|
||||
"rolling_slopes = pd.Series(slopes, index=rolling_dates)\n",
|
||||
"\n",
|
||||
"# Plot the original data and the rolling linear regression\n",
|
||||
"plt.figure(figsize=(14, 7))\n",
|
||||
"plt.plot(data, label='Original Data')\n",
|
||||
"for i in range(len(rolling_intercepts)):\n",
|
||||
" start_date = rolling_dates[i] - pd.DateOffset(days=window_size-1)\n",
|
||||
" end_date = rolling_dates[i]\n",
|
||||
" plt.plot([start_date, end_date],\n",
|
||||
" [rolling_intercepts[i], rolling_intercepts[i] + rolling_slopes[i] * (window_size - 1)],\n",
|
||||
" color='red', alpha=0.5)\n",
|
||||
"\n",
|
||||
"plt.legend()\n",
|
||||
"plt.title('Rolling Window Linear Regression')\n",
|
||||
"plt.xlabel('Date')\n",
|
||||
"plt.ylabel('Value')\n",
|
||||
"plt.show()\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
421
research/test1sbars.ipynb
Normal file
421
research/test1sbars.ipynb
Normal file
@ -0,0 +1,421 @@
|
||||
{
|
||||
"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",
|
||||
"\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",
|
||||
"res, df = load_batch(batch_id=\"0fb5043a\", #46 days 1.3 - 6.5.\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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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', '2024-04-23']).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",
|
||||
"start_date = pd.Timestamp('2024-03-12 09:30', tz=zoneNY)\n",
|
||||
"end_date = pd.Timestamp('2024-03-13 16:00', tz=zoneNY)\n",
|
||||
"\n",
|
||||
"#basic_data = basic_data.transform(lambda df: df[df.index.date == start_date.date()])\n",
|
||||
"#basic_data = basic_data.transform(lambda df: df[(df.index >= start_date) & (df.index <= end_date)])\n",
|
||||
"#basic_data.data[\"BAC\"].info()\n",
|
||||
"\n",
|
||||
"# fig = basic_data.plot(plot_volume=False)\n",
|
||||
"# pivot_info = basic_data.run(\"pivotinfo\", up_th=0.003, down_th=0.002)\n",
|
||||
"# #pivot_info.plot()\n",
|
||||
"# pivot_info.plot(fig=fig, conf_value_trace_kwargs=dict(visible=True))\n",
|
||||
"# fig.show()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# rsi14 = basic_data.data[\"BAC\"][\"Rsi14\"].rename(\"Rsi14\")\n",
|
||||
"\n",
|
||||
"# rsi14.vbt.plot().show()\n",
|
||||
"#basic_data.xloc[\"09:30\":\"10:00\"].data[\"BAC\"].vbt.ohlcv.plot().show()\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": [
|
||||
"# 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 = 1\n",
|
||||
"entry_window_closes = 350\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",
|
||||
"long_entries = (rsi.rsi.vbt.crossed_below(20) & entry_window_open)\n",
|
||||
"long_exits = (rsi.rsi.vbt.crossed_above(70) | forced_exit)\n",
|
||||
"#long_entries.info()\n",
|
||||
"#number of trues and falses in long_entries\n",
|
||||
"long_entries.value_counts()\n",
|
||||
"#long_exits.value_counts()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def plot_rsi(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(rsi.rsi, fig=fig, add_trace_kwargs=dict(secondary_y=False)) \n",
|
||||
" exits.vbt.signals.plot_as_exits(rsi.rsi, fig=fig, add_trace_kwargs=dict(secondary_y=False)) \n",
|
||||
" return fig\n",
|
||||
"\n",
|
||||
"plot_rsi(rsi, close, long_entries, long_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, entries=long_entries, sl_stop=sl_stop, tp_stop = sl_stop, exits=long_exits,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[(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(50, 'Total Return [%]')\n",
|
||||
"#stats_df.info()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pf[(0.0011,0.0013)].plot()\n",
|
||||
"\n",
|
||||
"#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
|
||||
}
|
||||
935
research/test1sbars_roc.ipynb
Normal file
935
research/test1sbars_roc.ipynb
Normal file
@ -0,0 +1,935 @@
|
||||
{
|
||||
"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",
|
||||
"\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",
|
||||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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 = [3, 7, 15, 29, 45, 50, 70]\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 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.03/100, 0.7/100, 0.05/100),4).tolist()\n",
|
||||
"tp_stop = np.round(np.arange(0.03/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 = 1000, 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=\"nextopen\") #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
|
||||
}
|
||||
Reference in New Issue
Block a user