680 lines
26 KiB
Plaintext
680 lines
26 KiB
Plaintext
{
|
|
"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
|
|
}
|