Files
strategy-lab/research/rsi_alpaca.ipynb

13 KiB

In [ ]:
from v2realbot.tools.loadbatch import load_batch
from v2realbot.utils.utils import zoneNY
import pandas as pd
import numpy as np
from datetime import timedelta, datetime
import vectorbtpro as vbt
import os
from itables import init_notebook_mode, show

init_notebook_mode(all_interactive=True)

vbt.settings.set_theme("dark")
vbt.settings['plotting']['layout']['width'] = 1280
vbt.settings.plotting.auto_rangebreaks = True
# Set the option to display with pagination
pd.set_option('display.notebook_repr_html', True)
pd.set_option('display.max_rows', 10)  # Number of rows per page

# Alpaca API credentials
ALPACA_API_KEY = os.environ.get('ACCOUNT1_PAPER_API_KEY')
ALPACA_API_SECRET = os.environ.get('ACCOUNT1_PAPER_SECRET_KEY')

# Initialize Alpaca data client
alpaca_data = vbt.AlpacaData.set_custom_settings(client_config=dict(
        api_key=ALPACA_API_KEY,
        secret_key=ALPACA_API_SECRET
    )
)

Fetch Data

In [ ]:
# Define the symbol, start, and end dates for your data
symbol = 'BAC'
start_date = datetime.now() - timedelta(days=10)  # Last 30 days
end_date = datetime.now() - timedelta(days=1)  # yesterday
time_interval = '1T'  # 1-minute intervals '1 minute'

basic_data = vbt.AlpacaData.pull(["BAC"], start=start_date, end=end_date, timeframe=time_interval, tz="America/New_York")
basic_data = basic_data.transform(lambda x: x.between_time("9:30","16:00"))
#basic_data.data["BAC"].vbt.ohlcv.plot()

filter dates

In [ ]:
#filter na dny
# dates_of_interest = pd.to_datetime(['2024-04-22', '2024-04-23']).tz_localize('US/Eastern')
# filtered_df = df.loc[df.index.normalize().isin(dates_of_interest)]

# df = filtered_df
# df.info()

basic_data.data["BAC"]
In [ ]:
m1_data = basic_data[['Open', 'High', 'Low', 'Close', 'Volume']]

m1_data.data["BAC"]
#m5_data = m1_data.resample("5T")

#m5_data.data["BAC"].head(10)

m15_data = m1_data.resample("15T")

m15_data = m15_data.transform(lambda x: x.between_time("9:30","15:59"))

m15 = m15_data.data["BAC"]

m15.vbt.ohlcv.plot()

m15

# m1_data.wrapper.index

# m1_resampler = m1_data.wrapper.get_resampler("1T")
# m1_resampler.index_difference(reverse=True)


# m5_resampler.prettify()

Calculate VWAP

In [ ]:
#WWAP
vbt.phelp(vbt.VWAP.run)
close = m1_data.close
high = m1_data.high
low = m1_data.low
volume = m1_data.volume
vwapD = vbt.VWAP.run(high, low, close, volume, anchor="D")
# vwapT = vbt.VWAP.run(high, low, close, volume, anchor="T")

#vwap.vwap

fig = m1_data.data["BAC"].vbt.ohlcv.plot()
vwapD.vwap.vbt.plot(fig=fig)
#vwapT.vwap.vbt.plot(fig=fig)
fig.show()

vwapD.vwap

#vwap = vbt.VWAP.run()
In [ ]:
m1_data.data["BAC"]

defining ENTRY WINDOW and forced EXIT window

In [ ]:
#m1_data.data["BAC"].info()
import datetime
# Define the market open and close times
market_open = datetime.time(9, 30)
market_close = datetime.time(16, 0)
entry_window_opens = 1
entry_window_closes = 350

forced_exit_start = 360
forced_exit_end = 390

forced_exit = m1_data.symbol_wrapper.fill(False)
entry_window_open=  m1_data.symbol_wrapper.fill(False)

# Calculate the time difference in minutes from market open for each timestamp
elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)

entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True
forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True

#entry_window_open.info()
# forced_exit.tail(100)
In [ ]:
close = m1_data.close

rsi = vbt.RSI.run(close, window=14)

long_entries = (rsi.rsi.vbt.crossed_below(28) & entry_window_open)
long_exits = (rsi.rsi.vbt.crossed_above(70) | forced_exit)
#long_entries.info()
#number of trues and falses in long_entries
#long_entries.value_counts()
long_exits.value_counts()
In [ ]:
close
In [ ]:
def plot_rsi(rsi, close, entries, exits):
    fig = vbt.make_subplots(rows=1, cols=1, shared_xaxes=True, specs=[[{"secondary_y": True}]], vertical_spacing=0.02, subplot_titles=("RSI", "Price" ))
    close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))
    rsi.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))
    entries.vbt.signals.plot_as_entries(close, fig=fig, add_trace_kwargs=dict(secondary_y=True))  
    exits.vbt.signals.plot_as_exits(close, fig=fig, add_trace_kwargs=dict(secondary_y=True))  
    return fig

plot_rsi(rsi, close, long_entries, long_exits)
In [ ]:
rsi.rsi
In [ ]:
vbt.phelp(vbt.Portfolio.from_signals)
In [ ]:
sl_stop = np.arange(0.03/100, 0.4/100, 0.05/100).tolist()
# Using the round function
sl_stop = [round(val, 4) for val in sl_stop]
print(sl_stop)
sl_stop = vbt.Param(sl_stop) #np.nan mean s no stoploss

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,

pf.stats()
In [ ]:
pf[(0.0003,0.0018)].plot()
In [ ]:
pf[0.03].plot_trade_signals()

pristup k pf jako multi index

In [ ]:
#pf[0.03].plot()
#pf.order_records
pf[(0.03)].stats()
In [ ]:
#zgrupovane statistiky
stats_df = pf.stats([
    'total_return',
    'total_trades',
    'win_rate',
    'expectancy'
], agg_func=None)
stats_df


stats_df.nlargest(10, 'Total Return [%]')
#stats_df.info()
In [ ]:
pf[(0.0011,0.0013000000000000002)].plot()
In [ ]:
from pandas.tseries.offsets import DateOffset

temp_data = basic_data['2024-4-22']
temp_data
res1m = temp_data[["Open", "High", "Low", "Close", "Volume"]]

# Define a custom date offset that starts at 9:30 AM and spans 4 hours
custom_offset = DateOffset(hours=4, minutes=30)

# res1m = res1m.get().resample("4H").agg({  
#     "Open": "first",
#     "High": "max",
#     "Low": "min",
#     "Close": "last",
#     "Volume": "sum"
# })

res4h = res1m.resample("1h", resample_kwargs=dict(origin="start"))

res4h.data

res15m = res1m.resample("15T", resample_kwargs=dict(origin="start"))

res15m.data["BAC"]
In [ ]:
@vbt.njit
def long_entry_place_func_nb(c, low, close, time_in_ns, rsi14, window_open, window_close):
    market_open_minutes = 570  # 9 hours * 60 minutes + 30 minutes

    for out_i in range(len(c.out)):
        i = c.from_i + out_i

        current_minutes = vbt.dt_nb.hour_nb(time_in_ns[i]) * 60 + vbt.dt_nb.minute_nb(time_in_ns[i])
        #print("current_minutes", current_minutes)
        # Calculate elapsed minutes since market open at 9:30 AM
        elapsed_from_open = current_minutes - market_open_minutes
        elapsed_from_open = elapsed_from_open if elapsed_from_open >= 0 else 0
        #print( "elapsed_from_open", elapsed_from_open)

        #elapsed_from_open = elapsed_minutes_from_open_nb(time_in_ns) 
        in_window = elapsed_from_open > window_open and elapsed_from_open < window_close
        #print("in_window", in_window)
        # if in_window:
        #     print("in window")

        if in_window and rsi14[i] > 60: # and low[i, c.col] <= hit_price: # and hour == 9:  # (4)!
            return out_i
    return -1

@vbt.njit
def long_exit_place_func_nb(c, high, close, time_index, tp, sl):  # (5)!
    entry_i = c.from_i - c.wait
    entry_price = close[entry_i, c.col]
    hit_price = entry_price * (1 + tp)
    stop_price = entry_price * (1 - sl)
    for out_i in range(len(c.out)):
        i = c.from_i + out_i
        last_bar_of_day = vbt.dt_nb.day_changed_nb(time_index[i], time_index[i + 1])

        #print(next_day)
        if last_bar_of_day: #pokud je dalsi next day, tak zavirame posledni
            print("ted",out_i)
            return out_i
        if close[i, c.col] >= hit_price or close[i, c.col] <= stop_price :
            return out_i
    return -1
In [ ]:
df = pd.DataFrame(np.random.random(size=(5, 10)), columns=list('abcdefghij'))

df
In [ ]:
df.sum()