Files
strategy-lab/to_explore/notebooks/MTFAnalysis.ipynb

1526 lines
36 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "257110ac-fb97-4051-adfe-81c1130b8cd2",
"metadata": {},
"source": [
"# MTF analysis"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "957fc6b1-f3b9-4778-ab72-28921aed1449",
"metadata": {},
"outputs": [],
"source": [
"from vectorbtpro import *\n",
"# whats_imported()\n",
"\n",
"vbt.settings.set_theme(\"dark\")"
]
},
{
"cell_type": "markdown",
"id": "c705f5df-b3ab-4a8f-8ea8-952d0cc6cd81",
"metadata": {},
"source": [
"## Data"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8356ce73-60e4-469e-b3b3-2e414b82eb5e",
"metadata": {},
"outputs": [],
"source": [
"# h1_data = vbt.BinanceData.pull(\n",
"# \"BTCUSDT\", \n",
"# start=\"2020-01-01 UTC\", \n",
"# end=\"2021-01-01 UTC\",\n",
"# timeframe=\"1h\"\n",
"# )\n",
"\n",
"# h1_data.to_hdf()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "06507a95-fc57-49db-9b97-62ccc4184055",
"metadata": {},
"outputs": [],
"source": [
"h1_data = vbt.HDFData.pull('BinanceData.h5')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2fab718a-09f2-4640-b477-dd681753ac53",
"metadata": {},
"outputs": [],
"source": [
"h1_data.wrapper.index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2a930576-729d-4c06-a9a3-6a8ad3de34e6",
"metadata": {},
"outputs": [],
"source": [
"h1_resampler = h1_data.wrapper.get_resampler(\"1h\")\n",
"h1_resampler.index_difference(reverse=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d4124583-e303-4eda-bfb0-f97e3908ef91",
"metadata": {},
"outputs": [],
"source": [
"h1_data.wrapper.columns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f39bc0ee-6e5c-4c87-93a3-1b5a31fe86f4",
"metadata": {},
"outputs": [],
"source": [
"h1_ohlcv_data = h1_data[[\"Open\", \"High\", \"Low\", \"Close\", \"Volume\"]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "461c8632-4e29-4b0d-8e85-72ea3b1754ae",
"metadata": {},
"outputs": [],
"source": [
"h4_ohlcv = h1_ohlcv_data.get().resample(\"4h\").agg({\n",
" \"Open\": \"first\",\n",
" \"High\": \"max\",\n",
" \"Low\": \"min\",\n",
" \"Close\": \"last\",\n",
" \"Volume\": \"sum\"\n",
"})\n",
"h4_ohlcv"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b84728de-a16b-417f-9ee8-ddafce9b24c3",
"metadata": {},
"outputs": [],
"source": [
"print(h1_ohlcv_data.get().iloc[:4])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "def713aa-9e46-488a-b100-83a563c5c30f",
"metadata": {},
"outputs": [],
"source": [
"print(h4_ohlcv.iloc[[0]])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e0d8b54-f1b6-4ff0-851e-c0cb8b8c415a",
"metadata": {},
"outputs": [],
"source": [
"print(vbt.prettify(vbt.BinanceData.feature_config))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5fcdcdbd-4274-4078-9e8f-5b64c4cd1e46",
"metadata": {},
"outputs": [],
"source": [
"h1_data.use_feature_config_of(vbt.BinanceData)\n",
"\n",
"h4_data = h1_data.resample(\"4h\")\n",
"d1_data = h1_data.resample(\"1d\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5980b577-d6ee-484d-8faf-9db6647dd29b",
"metadata": {},
"outputs": [],
"source": [
"print(d1_data.get().iloc[[0, -1]])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "000ebb64-4228-4967-aaac-2dc88975da61",
"metadata": {},
"outputs": [],
"source": [
"print(vbt.BinanceData.pull(\n",
" \"BTCUSDT\", \n",
" start=\"2020-01-01 UTC\", \n",
" end=\"2021-01-01 UTC\",\n",
" timeframe=\"1d\"\n",
").get().iloc[[0, -1]])"
]
},
{
"cell_type": "markdown",
"id": "f47840ab-b31d-49b3-bf24-d6406a2b542c",
"metadata": {},
"source": [
"## Alignment"
]
},
{
"cell_type": "markdown",
"id": "0c0ebc21-981a-4c09-8b38-2339e204cf5d",
"metadata": {},
"source": [
"### Pandas"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "73b897e3-4f35-41b2-a5c1-8f1c4010c0c2",
"metadata": {},
"outputs": [],
"source": [
"h1_close = h1_data.get(\"Close\")\n",
"h4_close = h4_data.get(\"Close\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9dccb01e-8056-4dc0-b5f6-0be44e3f5099",
"metadata": {},
"outputs": [],
"source": [
"h1_close.iloc[:4]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0a3a3c1c-0747-4a18-9462-863162dcdddb",
"metadata": {},
"outputs": [],
"source": [
"h4_close.iloc[:1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b1c22394-c1fc-4abc-8036-788848acbe92",
"metadata": {},
"outputs": [],
"source": [
"h1_h4_ratio = h1_close / h4_close\n",
"h1_h4_ratio.iloc[:4]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "acc7216c-0457-46a0-819d-a4675780f242",
"metadata": {},
"outputs": [],
"source": [
"h4_close_shifted = h4_close.shift()\n",
"h1_h4_ratio = h1_close / h4_close_shifted\n",
"h1_h4_ratio.iloc[:8]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e8dbbb29-8b79-4c8c-8ce8-5c2582434c95",
"metadata": {},
"outputs": [],
"source": [
"h1_h4_ratio.shift(-1).iloc[:8]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fd546cfa-559d-45a3-8e35-b2af75bd9df6",
"metadata": {},
"outputs": [],
"source": [
"h4_h1_close = h4_close.shift(1).resample(\"1h\").last().shift(-1).ffill()\n",
"h4_h1_close.iloc[:8]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ba830c23-074b-4ab9-ab4d-3b738a14be56",
"metadata": {},
"outputs": [],
"source": [
"fig = h1_close.rename(\"H1\").iloc[:16].vbt.plot()\n",
"h4_h1_close.rename(\"H4_H1\").iloc[:16].vbt.plot(fig=fig).show_svg()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6e8c73ee-5c05-4e95-89d0-ad195e138a96",
"metadata": {},
"outputs": [],
"source": [
"h1_h4_ratio = h1_close / h4_h1_close\n",
"h1_h4_ratio"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "023c506a-8e48-43e6-9244-9093c876edb0",
"metadata": {},
"outputs": [],
"source": [
"h1_open = h1_data.get(\"Open\")\n",
"h4_open = h4_data.get(\"Open\")\n",
"\n",
"h1_open.iloc[:8]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ca1bd16a-4157-43ba-be2f-61749ba83a3a",
"metadata": {},
"outputs": [],
"source": [
"h4_h1_open = h4_open.resample(\"1h\").first().ffill()\n",
"h4_h1_open.iloc[:8]"
]
},
{
"cell_type": "markdown",
"id": "ffcce240-8595-470d-b743-9b9f743f4543",
"metadata": {},
"source": [
"### VBT"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e90d2b3-d4b0-4b4f-ae19-fc6e0260ac16",
"metadata": {},
"outputs": [],
"source": [
"h4_close.vbt.realign_closing(\"1h\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "328daf52-40c4-40a8-9614-ea83c702f429",
"metadata": {},
"outputs": [],
"source": [
"h4_open.vbt.realign_opening(\"1h\")"
]
},
{
"cell_type": "markdown",
"id": "fceafe15-dd02-495f-bbcb-7978981dbfc8",
"metadata": {},
"source": [
"#### Resampler"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d9a79ae2-812a-4693-b68f-4b20246f86d4",
"metadata": {},
"outputs": [],
"source": [
"h4_h1_resampler = h4_close.vbt.wrapper.get_resampler(\"1h\")\n",
"h4_h1_resampler.source_index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75260aef-922a-46d9-b2c2-268247e57c20",
"metadata": {},
"outputs": [],
"source": [
"h4_h1_resampler.target_index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1bcb75a6-1808-4738-b746-80805817bd97",
"metadata": {},
"outputs": [],
"source": [
"h4_h1_resampler.source_freq"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eb51ba6c-2d10-4f4e-9d5e-432d515d72c4",
"metadata": {},
"outputs": [],
"source": [
"h4_h1_resampler.target_freq"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ef759223-074b-4961-87f4-47d9ab48e31a",
"metadata": {},
"outputs": [],
"source": [
"pd_resampler = h4_close.resample(\"1h\")\n",
"vbt.Resampler.from_pd_resampler(pd_resampler)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "402d9361-3657-46de-bf30-5a57d3006c50",
"metadata": {},
"outputs": [],
"source": [
"resampler = vbt.Resampler.from_date_range(\n",
" source_index=h4_close.index,\n",
" source_freq=\"4h\",\n",
" start=\"2020-01-01 10:00:00\",\n",
" end=\"2020-01-01 22:00:00\",\n",
" freq=\"1h\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "52df63ec-3951-4ed7-a1ea-18628dc9a0c0",
"metadata": {},
"outputs": [],
"source": [
"h4_close.vbt.realign_closing(resampler)"
]
},
{
"cell_type": "markdown",
"id": "beef78cd-9046-456f-8484-14e1e04b3c2f",
"metadata": {},
"source": [
"#### Custom index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "63ff2b4e-46b9-4ad3-8ef6-2f751ad7a9d8",
"metadata": {},
"outputs": [],
"source": [
"target_index = pd.Index([\n",
" \"2020-01-01\",\n",
" \"2020-02-01\",\n",
" \"2020-03-01\",\n",
" \"2020-04-01\",\n",
" \"2020-05-01\",\n",
" \"2020-06-01\",\n",
" \"2020-07-01\",\n",
" \"2020-08-01\",\n",
" \"2020-09-01\",\n",
" \"2020-10-01\",\n",
" \"2020-11-01\",\n",
" \"2020-12-01\",\n",
" \"2021-01-01\"\n",
"])\n",
"resampler = vbt.Resampler(h4_close.index, target_index, target_freq=False)\n",
"h4_close.vbt.realign_closing(resampler)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e5b6de84-d1a8-4d16-9677-fd8e7d8e5b1f",
"metadata": {},
"outputs": [],
"source": [
"h4_close[h4_close.index < \"2020-09-01\"].iloc[-1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3612f6b6-c960-4a10-b581-ccfbaf583cf8",
"metadata": {},
"outputs": [],
"source": [
"h4_open.vbt.realign_opening(resampler)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4fed1a9d-0867-49a1-bd20-4acf2d974e91",
"metadata": {},
"outputs": [],
"source": [
"h4_open[h4_open.index <= \"2020-08-01\"].iloc[-1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "063cfaaf-045c-40f4-be79-c177196c884b",
"metadata": {},
"outputs": [],
"source": [
"target_index = pd.Index([\n",
" \"2020-01-01\",\n",
" \"2020-02-01\",\n",
"])\n",
"resampler = vbt.Resampler(h4_close.index, target_index, target_freq=False)\n",
"h4_close.vbt.realign_closing(resampler)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5f3fb1cf-8646-4c71-b38a-b7631d94907e",
"metadata": {},
"outputs": [],
"source": [
"resampler = vbt.Resampler(h4_close.index, target_index, target_freq=\"30d\")\n",
"h4_close.vbt.realign_closing(resampler)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "07f61c2b-ea6a-4b6f-9633-760ce35901c1",
"metadata": {},
"outputs": [],
"source": [
"h4_open.vbt.realign(\"2020-06-07 12:15:00\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "42601b68-e4ea-4b70-b302-4f6bb2025969",
"metadata": {},
"outputs": [],
"source": [
"h4_close.vbt.realign(\n",
" \"2020-06-07 12:15:00\", \n",
" source_rbound=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8a5685b5-4847-4e59-8463-e7690bcf84f7",
"metadata": {},
"outputs": [],
"source": [
"h4_high = h4_data.get(\"High\")\n",
"h4_high.vbt.realign(\n",
" target_index, \n",
" source_rbound=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "65eb1d9f-a7a6-4c03-89ec-68db9685c1d1",
"metadata": {},
"outputs": [],
"source": [
"h4_high.index[h4_high.index < \"2020-02-01\"][-1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a9873388-768a-4ff5-a034-081779b3f879",
"metadata": {},
"outputs": [],
"source": [
"h4_high.vbt.realign(\n",
" target_index, \n",
" source_rbound=True,\n",
" target_rbound=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3be78c1c-1424-406c-b959-64bdc8cbd826",
"metadata": {},
"outputs": [],
"source": [
"resampler = vbt.Resampler(h4_high.index, target_index)\n",
"resampler.target_rbound_index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0631eb39-d180-461f-93c6-3b9c4b5efce2",
"metadata": {},
"outputs": [],
"source": [
"resampler = vbt.Resampler(\n",
" h4_high.index, \n",
" target_index, \n",
" target_freq=pd.offsets.MonthBegin(1))\n",
"resampler.target_rbound_index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b96efd81-4a14-4f65-8663-5d049b01a42b",
"metadata": {},
"outputs": [],
"source": [
"h4_high.vbt.realign(\n",
" resampler.replace(\n",
" target_index=resampler.target_rbound_index, \n",
" target_freq=False\n",
" ), \n",
" wrap_kwargs=dict(index=target_index)\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1e3f96e1-8161-4417-8201-5084aaec43ee",
"metadata": {},
"outputs": [],
"source": [
"h4_high.vbt.realign(\n",
" target_index, \n",
" freq=pd.offsets.MonthBegin(1),\n",
" target_rbound=\"pandas\"\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bac8e960-94ac-420a-81db-58db70a623d3",
"metadata": {},
"outputs": [],
"source": [
"h4_high[h4_high.index < \"2020-03-01\"].resample(vbt.offset(\"M\")).last()"
]
},
{
"cell_type": "markdown",
"id": "fa904b11-4aa9-4a3c-9990-4dfb17e5092f",
"metadata": {},
"source": [
"#### Numeric index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "acfcad7a-b094-4378-a380-8dd5dc8bc4ea",
"metadata": {},
"outputs": [],
"source": [
"resampler = vbt.Resampler(\n",
" source_index=np.arange(len(h4_high)),\n",
" target_index=np.arange(len(h4_high))[::6],\n",
" source_freq=1,\n",
" target_freq=6\n",
")\n",
"h4_high.vbt.realign(\n",
" resampler, \n",
" source_rbound=True,\n",
" target_rbound=True\n",
")"
]
},
{
"cell_type": "markdown",
"id": "d3ec6678-66b8-4a9d-92cf-a41ca96a9adb",
"metadata": {},
"source": [
"#### Forward filling"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3f27ab10-cba8-4c5f-97e6-e0533943795a",
"metadata": {},
"outputs": [],
"source": [
"min5_index = vbt.date_range(start=\"2020\", freq=\"5min\", periods=3)\n",
"min1_index = vbt.date_range(start=\"2020\", freq=\"1min\", periods=15)\n",
"min5_mask = pd.Series(False, index=min5_index)\n",
"min5_mask.iloc[0] = True\n",
"min5_mask.iloc[2] = True\n",
"\n",
"resampler = vbt.Resampler(min5_index, min1_index)\n",
"min1_mask = min5_mask.vbt.realign_closing(resampler)\n",
"min1_mask"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ab594857-24ea-4316-83e9-aa65c0be621c",
"metadata": {},
"outputs": [],
"source": [
"min1_mask = min5_mask.vbt.realign_closing(resampler, ffill=False)\n",
"min1_mask"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "053aeb5f-b8c1-46d5-849a-ec431e64ce8c",
"metadata": {},
"outputs": [],
"source": [
"min1_mask = min1_mask.fillna(False).astype(bool)\n",
"min1_mask"
]
},
{
"cell_type": "markdown",
"id": "0a220a77-0bd8-43f3-92ea-d532b883a793",
"metadata": {},
"source": [
"### Indicators"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5f1b6073-9e03-49cf-a212-83953d9910e3",
"metadata": {},
"outputs": [],
"source": [
"h4_sma = vbt.talib(\"SMA\").run(h4_data.get(\"Close\"), skipna=True).real\n",
"d1_sma = vbt.talib(\"SMA\").run(d1_data.get(\"Close\"), skipna=True).real\n",
"\n",
"h4_sma = h4_sma.ffill()\n",
"d1_sma = d1_sma.ffill()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "13ace4e8-4647-4f29-a516-142a94460a76",
"metadata": {},
"outputs": [],
"source": [
"resampler = vbt.Resampler(\n",
" d1_sma.index,\n",
" h4_sma.index,\n",
" source_freq=\"1d\",\n",
" target_freq=\"4h\"\n",
")\n",
"d1_h4_sma = d1_sma.vbt.realign_closing(resampler)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "837efa98-5a41-411f-91e4-7e07db205703",
"metadata": {},
"outputs": [],
"source": [
"d1_sma[\"2020-12-30\":]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6f4fab4d-05ec-4c96-be22-7d383ad493bb",
"metadata": {},
"outputs": [],
"source": [
"d1_h4_sma[\"2020-12-30\":]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1e4de9a1-e7e4-49f4-b2d4-f5afe1895cae",
"metadata": {},
"outputs": [],
"source": [
"entries = h4_sma.vbt.crossed_above(d1_h4_sma)\n",
"exits = h4_sma.vbt.crossed_below(d1_h4_sma)\n",
"\n",
"def plot_date_range(date_range):\n",
" fig = h4_sma[date_range].rename(\"H4\").vbt.plot()\n",
" d1_h4_sma[date_range].rename(\"D1_H4\").vbt.plot(fig=fig)\n",
" entries[date_range].rename(\"Entry\").vbt.signals.plot_as_entries(\n",
" y=h4_sma[date_range], fig=fig)\n",
" exits[date_range].rename(\"Exit\").vbt.signals.plot_as_exits(\n",
" y=h4_sma[date_range], fig=fig)\n",
" return fig\n",
"\n",
"plot_date_range(slice(\"2020-02-01\", \"2020-03-01\")).show_svg()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dfa7eae9-caff-49c9-b6cd-49216374cda5",
"metadata": {},
"outputs": [],
"source": [
"d1_open_sma = vbt.talib(\"SMA\").run(\n",
" d1_data.get(\"Open\"), \n",
" skipna=True\n",
").real\n",
"d1_open_sma = d1_open_sma.ffill()\n",
"\n",
"d1_h4_open_sma = d1_open_sma.vbt.realign(\n",
" resampler, \n",
" source_rbound=False,\n",
" target_rbound=True,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ab960235-1f29-4558-9e3b-c8f1d4ade177",
"metadata": {},
"outputs": [],
"source": [
"d1_open_sma[\"2020-12-30\":]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5cd93da8-2e9e-46a3-b2cc-576561baca66",
"metadata": {},
"outputs": [],
"source": [
"d1_h4_open_sma[\"2020-12-30\":]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9b7e7a74-9d26-486d-b1e9-47844c4c0d26",
"metadata": {},
"outputs": [],
"source": [
"def generate_bandwidths(freqs):\n",
" bandwidths = []\n",
" for freq in freqs:\n",
" close = h1_data.resample(freq).get(\"Close\")\n",
" bbands = vbt.talib(\"BBANDS\").run(close, skipna=True)\n",
" upperband = bbands.upperband.ffill()\n",
" middleband = bbands.middleband.ffill()\n",
" lowerband = bbands.lowerband.ffill()\n",
" bandwidth = (upperband - lowerband) / middleband\n",
" bandwidths.append(bandwidth.vbt.realign_closing(\"1h\"))\n",
" df = pd.concat(bandwidths, axis=1, keys=pd.Index(freqs, name=\"timeframe\"))\n",
" return df.ffill()\n",
"\n",
"bandwidths = generate_bandwidths([\"1h\", \"4h\", \"1d\", \"7d\"])\n",
"print(bandwidths)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b5349999-74d9-4106-924d-b8bfa44557b3",
"metadata": {},
"outputs": [],
"source": [
"bandwidths.loc[:, ::-1].vbt.ts_heatmap().show_svg()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5474bcdd-1096-46a4-97da-cb16ea310c26",
"metadata": {},
"outputs": [],
"source": [
">>> bbands = vbt.talib(\"BBANDS\").run(\n",
"... h1_data.get(\"Close\"), \n",
"... skipna=True, \n",
"... timeframe=[\"1h\", \"4h\", \"1d\", \"7d\"],\n",
"... broadcast_kwargs=dict(wrapper_kwargs=dict(freq=\"1h\"))\n",
"... )\n",
">>> bandwidth = (bbands.upperband - bbands.lowerband) / bbands.middleband\n",
">>> print(bandwidths)"
]
},
{
"cell_type": "markdown",
"id": "d0ab34e7-6b65-420a-b7ad-41626267a852",
"metadata": {},
"source": [
"### Testing"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3d012722-e263-4361-a2be-f77fd57ee53c",
"metadata": {},
"outputs": [],
"source": [
"def generate_signals(data, freq, fast_window, slow_window):\n",
" open_price = data.get(\"Open\").resample(freq).first()\n",
" fast_sma = vbt.talib(\"SMA\")\\\n",
" .run(\n",
" open_price, \n",
" fast_window, \n",
" skipna=True, \n",
" short_name=\"fast_sma\"\n",
" )\\\n",
" .real.ffill()\\\n",
" .vbt.realign(data.wrapper.index)\n",
" slow_sma = vbt.talib(\"SMA\")\\\n",
" .run(\n",
" open_price, \n",
" slow_window, \n",
" skipna=True, \n",
" short_name=\"slow_sma\"\n",
" )\\\n",
" .real.ffill()\\\n",
" .vbt.realign(data.wrapper.index)\n",
" entries = fast_sma.vbt.crossed_above(slow_sma)\n",
" exits = fast_sma.vbt.crossed_below(slow_sma)\n",
" return entries, exits\n",
"\n",
"fast_window = [10, 20]\n",
"slow_window = [20, 30]\n",
"h1_entries, h1_exits = generate_signals(h1_data, \"1h\", fast_window, slow_window)\n",
"h4_entries, h4_exits = generate_signals(h1_data, \"4h\", fast_window, slow_window)\n",
"d1_entries, d1_exits = generate_signals(h1_data, \"1d\", fast_window, slow_window)\n",
"\n",
"entries = pd.concat(\n",
" (h1_entries, h4_entries, d1_entries), \n",
" axis=1, \n",
" keys=pd.Index([\"1h\", \"4h\", \"1d\"], name=\"timeframe\")\n",
")\n",
"exits = pd.concat(\n",
" (h1_exits, h4_exits, d1_exits), \n",
" axis=1, \n",
" keys=pd.Index([\"1h\", \"4h\", \"1d\"], name=\"timeframe\")\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "be4a1fb7-231e-42a3-b113-a1e71173c96d",
"metadata": {},
"outputs": [],
"source": [
"(entries.astype(int) - exits.astype(int))\\\n",
" .resample(\"1d\").sum()\\\n",
" .vbt.ts_heatmap(\n",
" trace_kwargs=dict(\n",
" colorscale=[\"#ef553b\", \"rgba(0, 0, 0, 0)\", \"#17becf\"],\n",
" colorbar=dict(\n",
" tickvals=[-1, 0, 1], \n",
" ticktext=[\"Exit\", \"\", \"Entry\"]\n",
" )\n",
" )\n",
" ).show_svg()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8cbd506a-8911-400e-bbe3-fc439ae5e31d",
"metadata": {},
"outputs": [],
"source": [
"pf = vbt.Portfolio.from_signals(\n",
" h1_data,\n",
" entries,\n",
" exits,\n",
" sl_stop=0.1,\n",
" freq=\"1h\"\n",
")\n",
"\n",
"pf.orders.count()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "79f8734e-cfd3-4bb3-836f-5e4c96af1078",
"metadata": {},
"outputs": [],
"source": [
"pf.sharpe_ratio"
]
},
{
"cell_type": "markdown",
"id": "594dd6b4-814a-459a-9a68-a004471cbf55",
"metadata": {},
"source": [
"## Aggregation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e1a727a9-be21-4859-81c7-f660932dbfef",
"metadata": {},
"outputs": [],
"source": [
"ms_data = h1_data.resample(\"M\")\n",
"ms_data.get(\"Low\") / ms_data.get(\"High\") - 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ba41908f-77bb-41fd-92dc-3ddfb66660c7",
"metadata": {},
"outputs": [],
"source": [
"h1_high = h1_data.get(\"High\")\n",
"h1_low = h1_data.get(\"Low\")\n",
"ms_high = h1_high.resample(vbt.offset(\"M\")).max()\n",
"ms_low = h1_low.resample(vbt.offset(\"M\")).min()\n",
"ms_low / ms_high - 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4054b7a6-002d-40f7-8d81-906491355f2c",
"metadata": {},
"outputs": [],
"source": [
"ms_high = h1_high.vbt.resample_apply(\"M\", vbt.nb.max_reduce_nb)\n",
"ms_low = h1_low.vbt.resample_apply(\"M\", vbt.nb.min_reduce_nb)\n",
"ms_low / ms_high - 1"
]
},
{
"cell_type": "markdown",
"id": "5b8bc23f-95a4-4dd9-92cd-87e997979eb9",
"metadata": {},
"source": [
"### Custom index"
]
},
{
"cell_type": "markdown",
"id": "49646098-0314-4c0d-8ed2-361dc5316346",
"metadata": {},
"source": [
"#### Using target index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "286732d7-1ae7-4bd9-9a8e-8a7c21e7caab",
"metadata": {},
"outputs": [],
"source": [
"target_index = pd.Index([\n",
" \"2020-01-01\",\n",
" \"2020-02-01\",\n",
"])\n",
"h1_high.vbt.resample_to_index(\n",
" target_index, \n",
" vbt.nb.max_reduce_nb\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6c8f7530-3669-4b50-9cd8-933c638b47f9",
"metadata": {},
"outputs": [],
"source": [
"target_rbound_index = vbt.Resampler.get_rbound_index(\n",
" target_index, \n",
" pd.offsets.MonthBegin(1)\n",
")\n",
"h1_high.vbt.resample_to_index(\n",
" target_index.append(target_rbound_index[[-1]]), \n",
" vbt.nb.max_reduce_nb\n",
").iloc[:-1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "41025b95-36f3-40cb-ac84-8fd0168ef481",
"metadata": {},
"outputs": [],
"source": [
"h1_high[:\"2020-03-01\"].resample(vbt.offset(\"M\")).max().iloc[:-1]"
]
},
{
"cell_type": "markdown",
"id": "a2f6f226-2cdd-48b6-9a5c-9379dd2c6ec9",
"metadata": {},
"source": [
"#### Using group-by"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6ae265d2-195c-4045-9dcd-4180bb7ddb7b",
"metadata": {},
"outputs": [],
"source": [
"pd_resampler = h1_high.resample(vbt.offset(\"M\"))\n",
"ms_high = h1_high.vbt.groupby_apply(pd_resampler, vbt.nb.max_reduce_nb)\n",
"ms_low = h1_low.vbt.groupby_apply(pd_resampler, vbt.nb.min_reduce_nb)\n",
"ms_low / ms_high - 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b9a38ab9-18a0-4716-84cf-d276c945f2fd",
"metadata": {},
"outputs": [],
"source": [
"target_lbound_index = pd.Index([\n",
" \"2020-01-01\",\n",
" \"2020-02-01\",\n",
"])\n",
"target_rbound_index = pd.Index([\n",
" \"2020-02-01\",\n",
" \"2020-03-01\",\n",
"])\n",
"h1_high.vbt.resample_between_bounds(\n",
" target_lbound_index, \n",
" target_rbound_index,\n",
" vbt.nb.max_reduce_nb\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1b315822-a70c-4385-b0c4-2bc5c2b488eb",
"metadata": {},
"outputs": [],
"source": [
"h1_high.vbt.resample_between_bounds(\n",
" \"2020-01-01\", \n",
" vbt.date_range(\"2020-01-02\", \"2021-01-01\", freq=\"M\", inclusive=\"both\"),\n",
" vbt.nb.max_reduce_nb\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "170017dd-fb6d-47ca-b819-6498d018e9e8",
"metadata": {},
"outputs": [],
"source": [
"h1_high.expanding().max().resample(vbt.offset(\"M\")).max()"
]
},
{
"cell_type": "markdown",
"id": "24e72852-be2b-4b5b-bc60-d921491d1ab3",
"metadata": {},
"source": [
"### Meta methods"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "986fe4e4-f9f6-47d2-b415-a22e49723af4",
"metadata": {},
"outputs": [],
"source": [
"@njit\n",
"def mdd_nb(from_i, to_i, col, high, low):\n",
" highest = np.nanmax(high[from_i:to_i, col])\n",
" lowest = np.nanmin(low[from_i:to_i, col])\n",
" return lowest / highest - 1\n",
"\n",
"vbt.pd_acc.resample_apply(\n",
" \"M\",\n",
" mdd_nb,\n",
" vbt.Rep(\"high\"),\n",
" vbt.Rep(\"low\"),\n",
" broadcast_named_args=dict(\n",
" high=h1_high,\n",
" low=h1_low\n",
" )\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a83cb89f-90b9-4563-8124-79ea7938da70",
"metadata": {},
"outputs": [],
"source": [
"h1_high.iloc[0:744]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "41414c25-d863-4f83-a140-c1dfef1e4226",
"metadata": {},
"outputs": [],
"source": [
"h1_low.iloc[0:744].min() / h1_high.iloc[0:744].max() - 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "98949b71-5900-407f-b117-de2b7b50cd2e",
"metadata": {},
"outputs": [],
"source": [
">>> target_lbound_index = vbt.date_range(\"2020-01-01\", \"2020-12-01\", freq=\"M\", tz=\"UTC\", inclusive=\"both\")\n",
">>> target_rbound_index = vbt.date_range(\"2020-02-01\", \"2021-01-01\", freq=\"M\", tz=\"UTC\", inclusive=\"both\")\n",
">>> vbt.pd_acc.resample_between_bounds(\n",
"... target_lbound_index,\n",
"... target_rbound_index,\n",
"... mdd_nb,\n",
"... vbt.Rep(\"high\"),\n",
"... vbt.Rep(\"low\"),\n",
"... broadcast_named_args=dict(\n",
"... high=h1_high,\n",
"... low=h1_low\n",
"... )\n",
"... )"
]
},
{
"cell_type": "markdown",
"id": "d039d5e0-2562-44e1-b572-0345064bacfe",
"metadata": {},
"source": [
"### Numba"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cf993314-d0dc-42ae-a97c-3f38c237d67a",
"metadata": {},
"outputs": [],
"source": [
">>> from vectorbtpro.base.resampling.nb import map_bounds_to_source_ranges_nb\n",
"\n",
">>> range_starts, range_ends = map_bounds_to_source_ranges_nb(\n",
"... source_index=h1_high.index.values,\n",
"... target_lbound_index=target_lbound_index.values,\n",
"... target_rbound_index=target_rbound_index.values,\n",
"... closed_lbound=True,\n",
"... closed_rbound=False,\n",
"... )\n",
">>> np.column_stack((range_starts, range_ends))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ad3643dd-c3a4-4bc4-92b8-0c976fea9636",
"metadata": {},
"outputs": [],
"source": [
">>> ms_mdd_arr = vbt.nb.reduce_index_ranges_meta_nb(\n",
"... 1,\n",
"... range_starts,\n",
"... range_ends,\n",
"... mdd_nb,\n",
"... vbt.to_2d_array(h1_high),\n",
"... vbt.to_2d_array(h1_low)\n",
"... )\n",
">>> ms_mdd_arr"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "00aeb4d1-6f86-4470-9fe0-695823118b31",
"metadata": {},
"outputs": [],
"source": [
">>> pd.Series(ms_mdd_arr[:, 0], index=target_lbound_index)"
]
},
{
"cell_type": "markdown",
"id": "e8df7bde-fef1-421d-b09e-b454eb2286d9",
"metadata": {},
"source": [
"### Caveats"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "911d934a-5e38-4a62-a7f1-9a538f7b09a2",
"metadata": {},
"outputs": [],
"source": [
"h4_close_2d = h4_close.iloc[:12]\n",
"h4_close_2d"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "57f8392d-8fa2-4927-923f-ceb3bf1e9349",
"metadata": {},
"outputs": [],
"source": [
"h4_close_2d.resample(\"1d\").last()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1e7e3b5d-e6e7-463c-ae65-3b0b8915afa0",
"metadata": {},
"outputs": [],
"source": [
"h5_close = h1_close.resample(\"5h\").last()\n",
"h5_close_2d = h5_close.iloc[:10]\n",
"h5_close_2d"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f5fafb16-c6c3-4a6a-ab92-6f1d0122b603",
"metadata": {},
"outputs": [],
"source": [
"h5_close_2d.resample(\"1d\").last()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a45bfe1-fdcf-4e0b-b208-78aa32cc88b9",
"metadata": {},
"outputs": [],
"source": [
"vbt.timedelta(\"1d\") % vbt.timedelta(\"1h\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ab874a51-5c3f-442d-9b2f-238d3fc810ab",
"metadata": {},
"outputs": [],
"source": [
"vbt.timedelta(\"1d\") % vbt.timedelta(\"4h\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7f8129ea-1f41-412c-a86b-bde7bc42af2b",
"metadata": {},
"outputs": [],
"source": [
"vbt.timedelta(\"1d\") % vbt.timedelta(\"5h\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fcd15b36-44f9-4642-a976-9a341d12f2f5",
"metadata": {},
"outputs": [],
"source": [
"h5_close_time = h5_close_2d.index.shift() - pd.Timedelta(nanoseconds=1)\n",
"h5_close_time.name = \"Close time\"\n",
"h5_close_2d.index = h5_close_time\n",
"h5_close_2d"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "62befe68-5743-4901-b6eb-b654be33148b",
"metadata": {},
"outputs": [],
"source": [
"h5_close_2d.resample(\"1d\").last()"
]
},
{
"cell_type": "markdown",
"id": "6f5ad0b0-fe77-44c1-bcc2-4364c7ca15a3",
"metadata": {},
"source": [
"### Portfolio"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1c8b2cf1-a1e2-4acf-8eee-5568d93005eb",
"metadata": {},
"outputs": [],
"source": [
"fast_sma = vbt.talib(\"SMA\").run(h1_close, timeperiod=vbt.Default(10))\n",
"slow_sma = vbt.talib(\"SMA\").run(h1_close, timeperiod=vbt.Default(20))\n",
"entries = fast_sma.real_crossed_above(slow_sma.real)\n",
"exits = fast_sma.real_crossed_below(slow_sma.real)\n",
"\n",
"pf = vbt.Portfolio.from_signals(h1_close, entries, exits)\n",
"pf.plot().show_svg()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e50332b-8357-4b8d-9236-b2099eb13b62",
"metadata": {},
"outputs": [],
"source": [
"ms_pf = pf.resample(\"M\")\n",
"ms_pf.plot().show_svg()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "695b0602-710b-49ac-bf01-8eb981481dc7",
"metadata": {},
"outputs": [],
"source": [
"pf.total_return"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3c10ebcb-64ab-439d-b71e-0ab9e2645c6e",
"metadata": {},
"outputs": [],
"source": [
"ms_pf.total_return"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9821141f-89ad-465d-980c-632f0e8a4c17",
"metadata": {},
"outputs": [],
"source": [
"(1 + pf.returns).resample(vbt.offset(\"M\")).apply(lambda x: x.prod() - 1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ac16b57c-2148-4e85-a2a9-21909209c463",
"metadata": {},
"outputs": [],
"source": [
"ms_pf.returns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d5725b28-494d-4748-8959-27906374a239",
"metadata": {},
"outputs": [],
"source": [
"ms_pf.trades.pnl.to_pd(reduce_func_nb=\"sum\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a175390c-359d-49d9-8892-cfcce10e464b",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}