These 2 lines of code are the only two lines you have to change to make the bot work. You need to put here your own keys to Alpaca account. At the moment of creating this tutorial, Alpaca is free to use for everyone and with paper account you only need an email address to sign up.
#SuperAI Trading Bot
KEY_ID = "your own KEY_ID" #replace it with your own KEY_ID from Alpaca: https://alpaca.markets/
SECRET_KEY = "your own SECRET_KEY" #replace it with your own SECRET_KEY from Alpaca
You can choose any asset that can be traded with Alpaca API and paste the ticker of the asset in here.
#SuperAI Trading Bot
(asset, asset_type, rounding) = ("BTCUSD", "crypto", 0)
#if you want to trade crypto check: https://alpaca.markets/support/what-cryptocurrencies-does-alpaca-currently-support/
#rounding declares the no of numbers after comma for orders
#According to Alpaca:
#"All cryptocurrency assets are fractionable but the supported decimal points vary depending on the cryptocurrency."
#Check the smallest qty of the crypto you want to trade before declaring the 'rounding'
#read more about minimum qty and qty increment at https://alpaca.markets/docs/trading/crypto-trading/
#SuperAI Trading Bot
#(asset, asset_type, data_source) = ("AAPL", "stock", "Yahoo")
#if you want to trade stocks replace it with the ticker of the company you prefer: https://www.nyse.com/listings_directory/stock
#you can also use "Alpaca" as a data_source
#Alpaca gives you free access to more historical data, but in a free plan doesn't allow you to access data from last 15 minutes
#Yahoo gives you access to data from last 15 minutes, but gives you only 7 days of historical data with 1-min interval at a time
Here you can declare which technical indicators and candlestick patterns you want to use as signals to buy and sell stocks. You have:
You can create:
The initial logic of the bot is to:
(
)
#SuperAI Trading Bot
#@njit #you can unhash it if you have numba installed and imported and the bot should work a little faster, if you use njit
def create_signal(open_prices, high_prices, low_prices, close_prices, volume,
buylesstime, selltime, #Time to abstain from buying and forced selling
ma, ma_fast, ma_slow, #Moving Average
macd, macd_diff, macd_sign, #Moving Average Convergence Divergence
rsi, rsi_entry, rsi_exit, #Relative Strength Index
stoch, stoch_signal, stoch_entry, stoch_exit, #Stochastic
bb_low, bb_high, #Bollinger Bands
mfi, mfi_entry, mfi_exit, #Money Flow Index
candle_buy_signal_1, candle_buy_signal_2, candle_buy_signal_3, #Candle signals to buy
candle_sell_signal_1, candle_sell_signal_2, candle_sell_signal_3, #Candle signals to sell
candle_buy_sell_signal_1, candle_buy_sell_signal_2): #Candle signals to buy or sell
SuperAI_signal_buy = np.where(
(buylesstime != 1)
&
(
(
((ma_fast < ma_slow) & (rsi < rsi_entry))
|
(close_prices < bb_low)
|
(mfi < mfi_entry)
#|
#(close_prices > ma)
#|
#(macd < 0)
#|
#(macd_diff < 0)
#|
#(macd_sign < macd)
#|
#(stoch < stoch_entry)
#|
#(stoch_signal < stoch_entry)
#|
#((close_prices > ma) & (ma_fast > ma_slow))
#|
#(((rsi < rsi_entry) & ((close_prices < ma) | (macd < 0))))
#|
#((close_prices > ma) & (shifted(close_prices, 1) < ma))
#|
#((stoch < stoch_entry) & (
# (ma > (shifted(ma, 1))) &
# (shifted(ma, 1) > (shifted(ma, 2)))))
#|
#((rsi < rsi_entry) & (
# ~((ma > (shifted(ma, 2) * 1.01)) &
# (shifted(ma, 2) > (shifted(ma, 4)*1.01)))))
)
|
((candle_buy_signal_1 > 0) | (candle_buy_signal_2 > 0) | (candle_buy_signal_3 > 0)
| (candle_buy_sell_signal_1 > 0) | (candle_buy_sell_signal_2 > 0))
)
, 1, 0) #1 is buy, -1 is sell, 0 is do nothing
SuperAI_signal = np.where(
(selltime == 1)
#|
#(ma_fast > ma_slow)
|
(rsi > rsi_exit)
|
(close_prices > bb_high)
|
(mfi > mfi_exit)
#|
#(close_prices < ma)
#|
#(macd_diff > 0)
#|
#(macd_sign > macd)
#|
#(stoch > stoch_exit)
#|
#(stoch_signal > stoch_exit)
#|
#((close_prices < ma) & (rsi > rsi_exit))
#|
#(((rsi > rsi_exit) & ((close_prices < ma) | (macd > 3))))
#|
#((close_prices < ma) & (shifted(close_prices, 1) > ma))
#|
#((stoch > stoch_exit) & (
# (ma > (shifted(ma, 1))) &
# (shifted(ma, 1) > (shifted(ma, 2)))))
|
((candle_sell_signal_1 < 0) | (candle_sell_signal_2 < 0) | (candle_buy_signal_3 < 0)
| (candle_buy_sell_signal_1 < 0) | (candle_buy_sell_signal_2 < 0))
, -1, SuperAI_signal_buy) #1 is buy, -1 is sell, 0 is do nothing
return SuperAI_signal
#SuperAI Trading Bot
take_profit_percent = 0.05 # 5%
stop_loss_percent = 0.001 # 0.1%
#SuperAI Trading Bot
def trading_buy_sell_time():
if asset_type == 'stock':
#more about trading hours at: https://alpaca.markets/docs/trading/orders/#extended-hours-trading
trading_hour_start = "09:30"
trading_hour_stop = "16:00"
#time when you don't want to buy at the beginning of the day
buyless_time_start_1 = "09:30"
buyless_time_end_1 = "09:45"
buyless_time_start_2 = "15:55"
buyless_time_end_2 = "16:00"
#time when you want to sell by the end of the day
selltime_start = "15:55"
selltime_end = "16:00"
elif asset_type == 'crypto':
trading_hour_start = "00:00"
trading_hour_stop = "23:59"
#time when you don't want to buy at the beginning of the day
buyless_time_start_1 = "23:59"
buyless_time_end_1 = "00:01"
buyless_time_start_2 = "23:58"
buyless_time_end_2 = "23:59"
#time when you want to sell by the end of the day
selltime_start = "23:59"
selltime_end = "00:00"
return (trading_hour_start, trading_hour_stop,
buyless_time_start_1, buyless_time_end_1, buyless_time_start_2, buyless_time_end_2,
selltime_start, selltime_end)
#SuperAI Trading Bot
(trading_hour_start, trading_hour_stop,
buyless_time_start_1, buyless_time_end_1, buyless_time_start_2, buyless_time_end_2,
selltime_start, selltime_end) = trading_buy_sell_time()
(trading_hour_start, trading_hour_stop,
buyless_time_start_1, buyless_time_end_1, buyless_time_start_2, buyless_time_end_2,
selltime_start, selltime_end)
#SuperAI Trading Bot
#helper function to shift data in order to test differences between data from x min and data from x-time min
def shifted(data, shift_window):
data_shifted = np.roll(data, shift_window)
if shift_window >= 0:
data_shifted[:shift_window]=np.NaN
elif shift_window < 0:
data_shifted[shift_window:]=np.NaN
return data_shifted
#SuperAI Trading Bot
# Moving Average
ma_timeframe = 28
ma_fast_timeframe = 14
ma_slow_timeframe = 50
#SuperAI Trading Bot
# Moving Average Convergence Divergence
macd_slow_timeframe = 26
macd_fast_timeframe = 12
macd_signal_timeframe = 9
#SuperAI Trading Bot
# Relative Strength Index
rsi_timeframe = 14
rsi_oversold_threshold = 30
rsi_overbought_threshold = 70
#SuperAI Trading Bot
#Stochastic Indicator
stoch_timeframe = 14
stoch_smooth_timeframe = 3
stoch_oversold_threshold = 20
stoch_overbought_threshold = 80
#SuperAI Trading Bot
# Bollinger Bands
bb_timeframe = 10
bb_dev = 2
#SuperAI Trading Bot
# Money Flow Index
mfi_timeframe = 14
mfi_oversold_threshold = 20
mfi_overbought_threshold = 80
#SuperAI Trading Bot
ma_window = ma_timeframe
ma_fast_window = ma_fast_timeframe
ma_slow_window = ma_slow_timeframe
macd_slow_window = macd_slow_timeframe
macd_fast_window = macd_fast_timeframe
macd_sign_window = macd_signal_timeframe
rsi_window = rsi_timeframe
rsi_entry = rsi_oversold_threshold
rsi_exit = rsi_overbought_threshold
stoch_window = stoch_timeframe
stoch_smooth_window = stoch_smooth_timeframe
stoch_entry = stoch_oversold_threshold
stoch_exit = stoch_overbought_threshold
bb_window = bb_timeframe
bb_dev = bb_dev
mfi_window = mfi_timeframe
mfi_entry = mfi_oversold_threshold
mfi_exit = mfi_overbought_threshold
#SuperAI Trading Bot
(ma_window_max, ma_fast_window_max, ma_slow_window_max,
macd_slow_window_max, macd_fast_window_max, macd_sign_window_max,
rsi_window_max, rsi_entry_max, rsi_exit_max,
stoch_window_max, stoch_smooth_window_max, stoch_entry_max, stoch_exit_max,
bb_window_max, bb_dev_max, mfi_window_max,
mfi_entry_max, mfi_exit_max) = (ma_window, ma_fast_window, ma_slow_window,
macd_slow_window, macd_fast_window, macd_sign_window,
rsi_window, rsi_entry, rsi_exit,
stoch_window, stoch_smooth_window, stoch_entry, stoch_exit,
bb_window, bb_dev, mfi_window,
mfi_entry, mfi_exit)
(ma_window_max, ma_fast_window_max, ma_slow_window_max,
macd_slow_window_max, macd_fast_window_max, macd_sign_window_max,
rsi_window_max, rsi_entry_max, rsi_exit_max,
stoch_window_max, stoch_smooth_window_max, stoch_entry_max, stoch_exit_max,
bb_window_max, bb_dev_max, mfi_window_max,
mfi_entry_max, mfi_exit_max)
At first, we install all the necessary libraries and packages. You can skip it if you already have them installed or you can upgrade them.
#SuperAI Trading Bot
!pip install alpaca-trade-api --upgrade
#https://pypi.org/project/alpaca-trade-api/
#SuperAI Trading Bot
!pip install numpy --upgrade
#https://pypi.org/project/numpy/
#SuperAI Trading Bot
!pip install pandas --upgrade
#https://pypi.org/project/pandas/
#SuperAI Trading Bot
!pip install ta --upgrade
#https://pypi.org/project/ta/
#SuperAI Trading Bot
#!pip install TA-Lib --upgrade
#https://pypi.org/project/TA-Lib/
#or if it doesn't work on Windows and you are using Anaconda,
#try writing in Anaconda Prompt: conda install -c conda-forge ta-lib
#SuperAI Trading Bot
!pip install vectorbt --upgrade
#https://pypi.org/project/vectorbt/
#SuperAI Trading Bot
!pip install yfinance --upgrade
#https://pypi.org/project/yfinance/
Now, that we have everything installed we can import it to our program.
#SuperAI Trading Bot
import alpaca_trade_api as tradeapi
from alpaca_trade_api.rest import TimeFrame
import ast
import datetime
from datetime import timedelta
import json
import math
import numpy as np
import pandas as pd
import plotly
import plotly.express as px
import plotly.graph_objects as go
import sys
import ta
import talib as ta_lib
import time
import vectorbt as vbt
print("Python version: {}".format(sys.version))
print("alpaca trade api version: {}".format(tradeapi.__version__))
print("json version: {}".format(json.__version__))
print("numpy version: {}".format(np.__version__))
print("pandas version: {}".format(pd.__version__))
print("plotly version: {}".format(plotly.__version__))
print("ta_lib version: {}".format(ta_lib.__version__))
print("vectorbt version: {}".format(vbt.__version__))
pip show ta
#warnings are preinstalled with anaconda, so we don't have to install it
import warnings
warnings.filterwarnings('ignore')
#!pip install numba --upgrade
#https://pypi.org/project/numba/
#or if it doesn't work on Windows and you are using Anaconda,
#try writing in Anaconda Prompt: conda install numba
#import numba
#from numba import njit
#print("numba version: {}".format(numba.__version__))
The URLs we use here are for paper trading. If you want to use your bot with your live account, you should change these URLs to those dedicated to live account at Alpaca. Just remember, that with live account you are using real money, so be sure that your bot works as you want it to work. Test your bot before you give it real money to trade.
If you want to use this bot with your paper account as we do in this tutorial, you can leave these two cells as they are.
#SuperAI Trading Bot
APCA_API_BASE_URL = "https://paper-api.alpaca.markets"
#change if you want to use the bot with your live account
#SuperAI Trading Bot
api = tradeapi.REST(KEY_ID, SECRET_KEY, APCA_API_BASE_URL, "v2")
#check if you are connected to Alpaca
nyc_datetime = api.get_clock().timestamp.tz_convert('America/New_York')
print("I'm connected to Alpaca and it's {} in New York at the moment. Let's have some fun.".format(str(nyc_datetime)[:16]))
#SuperAI Trading Bot
vbt.settings.data['alpaca']['key_id'] = KEY_ID
vbt.settings.data['alpaca']['secret_key'] = SECRET_KEY
#SuperAI Trading Bot
data_timeframe = '1m' #replace with preferable time between data: 1m, 5m, 15m, 30m, 1h, 1d
data_limit = None #replace with the limit of the data to download to speed up the process (500, 1000, None)
crypto_data_timeframe = TimeFrame.Minute
preferred_exchange = "CBSE"
data_start = '2022-05-30' #replace with the starting point for collecting data
data_end = '2022-06-06' #replace with the ending point for collecting the data
#SuperAI Trading Bot
#preparing data in one function
def prepare_data(start_date, end_date):
data_start = start_date
data_end = end_date
if asset_type == "stock" and data_source == "Alpaca":
full_data = vbt.AlpacaData.download(asset, start=data_start, end=data_end,
timeframe=data_timeframe, limit=data_limit).get()
elif asset_type == "stock" and data_source == "Yahoo":
full_data = vbt.YFData.download(asset, start = data_start, end= data_end,
interval=data_timeframe).get().drop(["Dividends", "Stock Splits"], axis=1)
elif asset_type == "crypto":
crypto_data = api.get_crypto_bars(asset, crypto_data_timeframe, start = data_start, end=data_end).df
full_crypto_data = crypto_data[crypto_data['exchange'] == preferred_exchange]
full_data = full_crypto_data.rename(str.capitalize, axis=1).drop(["Exchange", "Trade_count", "Vwap"], axis=1)
else:
print("You have to declare asset type as crypto or stock for me to work properly.")
full_data.index = full_data.index.tz_convert('America/New_York')
(trading_hour_start, trading_hour_stop,
buyless_time_start_1, buyless_time_end_1, buyless_time_start_2, buyless_time_end_2,
selltime_start, selltime_end) = trading_buy_sell_time()
data = full_data.copy()
data = data.between_time(trading_hour_start, trading_hour_stop)
not_time_to_buy_1 = data.index.indexer_between_time(buyless_time_start_1, buyless_time_end_1)
not_time_to_buy_2 = data.index.indexer_between_time(buyless_time_start_2, buyless_time_end_2)
not_time_to_buy = np.concatenate((not_time_to_buy_1, not_time_to_buy_2), axis=0)
not_time_to_buy = np.unique(not_time_to_buy)
data["NotTimeToBuy"] = 1
data["BuylessTime"] = data.iloc[not_time_to_buy, 5]
data["BuylessTime"] = np.where(np.isnan(data["BuylessTime"]), 0, data["BuylessTime"])
data = data.drop(["NotTimeToBuy"], axis=1)
time_to_sell = data.index.indexer_between_time(selltime_start, selltime_end)
data["TimeToSell"] = 1
data["SellTime"] = data.iloc[time_to_sell, 6]
data["SellTime"] = np.where(np.isnan(data["SellTime"]), 0, data["SellTime"])
data = data.drop(["TimeToSell"], axis=1)
open_prices = data["Open"]
high_prices = data["High"]
low_prices = data["Low"]
close_prices = data["Close"]
volume = data["Volume"]
buylesstime = data["BuylessTime"]
selltime = data["SellTime"]
return open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime
#open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime = prepare_data(data_start, data_end)
#downloading stock data with vbt from Alpaca or Yahoo: https://vectorbt.dev/api/data/custom/
#downloading crypto data directly from Alpaca: https://alpaca.markets/learn/getting-started-with-alpaca-crypto-api/
if asset_type == "stock" and data_source == "Alpaca":
full_data = vbt.AlpacaData.download(asset, start=data_start, end=data_end, timeframe=data_timeframe, limit=data_limit).get()
elif asset_type == "stock" and data_source == "Yahoo":
full_data = vbt.YFData.download(asset, start = data_start, end= data_end, interval=data_timeframe).get().drop(
["Dividends", "Stock Splits"], axis=1)
elif asset_type == "crypto":
crypto_data = api.get_crypto_bars(asset, crypto_data_timeframe, start = data_start, end=data_end).df
full_crypto_data = crypto_data[crypto_data['exchange'] == preferred_exchange]
full_data = full_crypto_data.rename(str.capitalize, axis=1).drop(["Exchange", "Trade_count", "Vwap"], axis=1)
full_data
full_data.index = full_data.index.tz_convert('America/New_York')
full_data
full_data.vbt.ohlcv.plot()
data = full_data.copy()
data = data.between_time(trading_hour_start, trading_hour_stop)
data
data.vbt.ohlcv.plot()
not_time_to_buy_1 = data.index.indexer_between_time(buyless_time_start_1, buyless_time_end_1)
not_time_to_buy_2 = data.index.indexer_between_time(buyless_time_start_2, buyless_time_end_2)
not_time_to_buy = np.concatenate((not_time_to_buy_1, not_time_to_buy_2), axis=0)
not_time_to_buy = np.unique(not_time_to_buy)
not_time_to_buy
data["NotTimeToBuy"] = 1
data["BuylessTime"] = data.iloc[not_time_to_buy, 5]
data["BuylessTime"] = np.where(np.isnan(data["BuylessTime"]), 0, data["BuylessTime"])
data = data.drop(["NotTimeToBuy"], axis=1)
data
time_to_sell = data.index.indexer_between_time(selltime_start, selltime_end)
time_to_sell
data["TimeToSell"] = 1
data["SellTime"] = data.iloc[time_to_sell, 6]
data["SellTime"] = np.where(np.isnan(data["SellTime"]), 0, data["SellTime"])
data = data.drop(["TimeToSell"], axis=1)
data
open_prices = data["Open"]
high_prices = data["High"]
low_prices = data["Low"]
close_prices = data["Close"]
volume = data["Volume"]
buylesstime = data["BuylessTime"]
selltime = data["SellTime"]
print(buylesstime.to_string())
There are different types of MA (SMA, WMA, EMA)
You can read more at Investopedia:
# TREND
#TREND: SMA Simple Moving Average
data['sma'] = ta.trend.sma_indicator(close_prices, window =14)
#TREND: WMA Weighted Moving Average
data['wma'] = ta.trend.wma_indicator(close_prices, window = 14)
#TREND: EMA Exponential Moving Average (with different time windows)
data['ema'] = ta.trend.ema_indicator(close_prices, window = 28)
data['ema_fast'] = ta.trend.ema_indicator(close_prices, window = 14)
data['ema_slow'] = ta.trend.ema_indicator(close_prices, window = 50)
data.iloc[10:20, 3:]
(close_prices < ma) & (shifted(close_prices, 1) > shifted(ma,1))
data['close_shifted'] = shifted(close_prices, 1)
data['ma shifted'] = shifted(data['sma'], 1)
data.iloc[:20, 3:]
data = data.drop(["ma shifted"], axis=1)
(close_prices < ma) & (shifted(close_prices, 1) > shifted(ma, 1))
vbt.MA.run(data.iloc[:90]['Close'], 14).plot()
You can read more about Moving Average Convergence Divergence (MACD) here: https://www.investopedia.com/terms/m/macd.asp
#TREND: MACD (Moving Average Convergence Divergence)
data['macd'] = ta.trend.macd(close_prices, window_slow = 26, window_fast = 12)
data['macd_diff'] = ta.trend.macd_diff(close_prices, window_slow = 26, window_fast = 12, window_sign = 9)
data['macd_signal'] = ta.trend.macd_signal(close_prices, window_slow = 26, window_fast = 12, window_sign = 9)
data.iloc[20:35, 12:]
(macd < 0) | (macd_diff < 0) | (macd_sign < macd)
vbt.MACD.run(data.iloc[:90]['Close'], 14).plot()
You can read more about:
RSI: https://www.investopedia.com/terms/r/rsi.asp
Stochastic: https://www.investopedia.com/terms/s/stochasticoscillator.asp
# MOMENTUM: RSI (Relative Strength Index)
data['rsi'] = ta.momentum.rsi(close_prices, window = 14)
# MOMENTUM: Stoch (Stochastic)
data['stoch'] = ta.momentum.stoch(high_prices, low_prices, close_prices, window = 14, smooth_window = 3)
data['stoch_signal'] = ta.momentum.stoch_signal(high_prices, low_prices, close_prices, window=14, smooth_window=3)
data.iloc[10:20, 15:]
(rsi < rsi_entry)
vbt.RSI.run(data.iloc[:90]['Close']).plot()
(stoch < stoch_entry) | (stoch_signal < stoch_entry)
vbt.STOCH.run(data['High'][:90], data['Low'][:90], data['Close'][:90]).plot()
((stoch < stoch_entry) & ((ma > (shifted(ma, 1))) & (shifted(ma, 1) > (shifted(ma, 2)))))
data['ema_not_shifted'] = data['ema_fast']
data['ema_sh_1'] = shifted(data['ema_fast'], 1)
data['ema_sh_2'] = shifted(data['ema_fast'], 2)
data.iloc[10:25, 16:]
((ma > (shifted(ma, 1))) & (shifted(ma, 1) > (shifted(ma, 2))))
vbt.MA.run(data.iloc[:90]['Close'], 14).plot()
((rsi < rsi_entry) & (~((ma > (shifted(ma, 2) 1.01)) & (shifted(ma, 2) > (shifted(ma, 4)1.01)))))
data['ema_sh_5_101'] = shifted(data['ema_fast'], 2)*1.01
data['ema_sh_10_101'] = shifted(data['ema_fast'], 4)*1.01
data.iloc[10:20, 16:]
(why You should always use libraries calculating technical indicators with caution)
How RSI is calculated? https://www.investopedia.com/terms/r/rsi.asp
data_rsi = data.copy()
data_rsi.drop(data_rsi.iloc[:, 5:], inplace = True, axis = 1)
data_rsi
test_close_rsi = data_rsi["Close"].to_numpy()
data_rsi['rsi_vbt'] = vbt.RSI.run(test_close_rsi, 14).rsi.to_numpy()
data_rsi['rsi_talib'] = vbt.IndicatorFactory.from_talib('RSI').run(test_close_rsi, 14).real.to_numpy()
data_rsi['rsi_ta'] = vbt.IndicatorFactory.from_ta('RSIIndicator').run(test_close_rsi, 14).rsi.to_numpy()
data_rsi.iloc[10:20,:]
You can read more about Bollinger Bands here: https://www.investopedia.com/terms/b/bollingerbands.asp
# VOLATILITY: BB (Bollinger Bands)
data["bb_low"] = ta.volatility.bollinger_lband(close_prices, window=14, window_dev = 2)
data["bb_high"] = ta.volatility.bollinger_hband(close_prices, window=14, window_dev = 2)
data.iloc[10:20, 20:]
vbt.BBANDS.run(data['Close'][:90]).plot()
You can read more about MFI here: https://www.investopedia.com/terms/m/mfi.asp
# VOLUME: MFI (Money Flow Index (='volume-weighted RSI'))
data['mfi'] = ta.volume.money_flow_index(high_prices, low_prices, close_prices, volume, window = 14)
data.iloc[10:20, 24:]
px.line(data['mfi'][:90], title='Money Flow Index')
You can read more about candlestick patterns here:
# CandleStick Patterns Signals
# candle buy signal 'Hammer'
data["c_buy_1"] = ta_lib.CDLHAMMER(open_prices, high_prices, low_prices, close_prices)
# candle buy signal 'Morning Star'
data["c_buy_2"] = ta_lib.CDLMORNINGSTAR(open_prices, high_prices, low_prices, close_prices)
# candle buy signal '3 White Soldiers'
data["c_buy_3"] = ta_lib.CDL3WHITESOLDIERS(open_prices, high_prices, low_prices, close_prices)
# candle sell signal 'Shooting Star'
data["c_sell_1"] = ta_lib.CDLSHOOTINGSTAR(open_prices, high_prices, low_prices, close_prices)
# candle sell signal 'Evening Star'
data["c_sell_2"] = ta_lib.CDLEVENINGSTAR(open_prices, high_prices, low_prices, close_prices)
# candle sell signal '3 Black Crows'
data["c_sell_3"] = ta_lib.CDL3BLACKCROWS(open_prices, high_prices, low_prices, close_prices)
# candle buy/sell signal 'Engulfing Bullish / Bearish'
data["c_bs_1"] = ta_lib.CDLENGULFING(open_prices, high_prices, low_prices, close_prices)
# candle buy/sell signal '3 Outside Up / Down'
data["c_bs_2"] = ta_lib.CDL3OUTSIDE(open_prices, high_prices, low_prices, close_prices)
data.iloc[30:50, 26:]
((candle_buy_signal_1 > 0) | (candle_buy_signal_2 > 0) | (candle_buy_signal_3 > 0) | (candle_buy_sell_signal_1 > 0) | (candle_buy_sell_signal_2 > 0))
go.Figure(data=[go.Candlestick(x=data.index[10:70],
open=data['Open'][10:70],
high=data['High'][10:70],
low=data['Low'][10:70],
close=data['Close'][10:70])])
def superai_signals (open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime,
ma_window = ma_timeframe,
ma_fast_window = ma_fast_timeframe,
ma_slow_window = ma_slow_timeframe,
macd_slow_window = macd_slow_timeframe,
macd_fast_window = macd_fast_timeframe,
macd_sign_window = macd_signal_timeframe,
rsi_window = rsi_timeframe,
rsi_entry = rsi_oversold_threshold,
rsi_exit = rsi_overbought_threshold,
stoch_window = stoch_timeframe,
stoch_smooth_window = stoch_smooth_timeframe,
stoch_entry = stoch_oversold_threshold,
stoch_exit = stoch_overbought_threshold,
bb_window = bb_timeframe,
bb_dev = bb_dev,
mfi_window = mfi_timeframe,
mfi_entry = mfi_oversold_threshold,
mfi_exit = mfi_overbought_threshold):
rsi = vbt.IndicatorFactory.from_ta('RSIIndicator').run(close_prices, window = rsi_window).rsi.to_numpy()
stoch = vbt.IndicatorFactory.from_ta('StochasticOscillator').run(
high_prices, low_prices, close_prices, window = stoch_window, smooth_window = stoch_smooth_window).stoch.to_numpy()
stoch_signal = vbt.IndicatorFactory.from_ta('StochasticOscillator').run(
high_prices, low_prices, close_prices, window = stoch_window,
smooth_window = stoch_smooth_window).stoch_signal.to_numpy()
ma = vbt.IndicatorFactory.from_ta('EMAIndicator').run(close_prices, window = ma_window).ema_indicator.to_numpy()
ma_fast = vbt.IndicatorFactory.from_ta('EMAIndicator').run(close_prices, window = ma_fast_window).ema_indicator.to_numpy()
ma_slow = vbt.IndicatorFactory.from_ta('EMAIndicator').run(close_prices, window = ma_slow_window).ema_indicator.to_numpy()
macd = vbt.IndicatorFactory.from_ta('MACD').run(
close_prices, window_slow = macd_slow_window, window_fast = macd_fast_window,
window_sign = macd_sign_window).macd.to_numpy()
macd_diff = vbt.IndicatorFactory.from_ta('MACD').run(
close_prices, macd_slow_window, window_fast = macd_fast_window,
window_sign = macd_sign_window).macd_diff.to_numpy()
macd_sign = vbt.IndicatorFactory.from_ta('MACD').run(
close_prices, macd_slow_window, window_fast = macd_fast_window,
window_sign = macd_sign_window).macd_signal.to_numpy()
bb_low = vbt.IndicatorFactory.from_ta('BollingerBands').run(
close_prices, window = bb_window, window_dev = bb_dev).bollinger_lband.to_numpy()
bb_high = vbt.IndicatorFactory.from_ta('BollingerBands').run(
close_prices, window = bb_window, window_dev = bb_dev).bollinger_hband.to_numpy()
mfi = vbt.IndicatorFactory.from_ta('MFIIndicator').run(
high_prices, low_prices, close_prices, volume, window = mfi_timeframe).money_flow_index.to_numpy()
candle_buy_signal_1 = vbt.IndicatorFactory.from_talib('CDLHAMMER').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # 'Hammer'
candle_buy_signal_2 = vbt.IndicatorFactory.from_talib('CDLMORNINGSTAR').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # 'Morning star'
candle_buy_signal_3 = vbt.IndicatorFactory.from_talib('CDL3WHITESOLDIERS').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # 'Three White Soldiers'
candle_sell_signal_1 = vbt.IndicatorFactory.from_talib('CDLSHOOTINGSTAR').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # 'Shooting star'
candle_sell_signal_2 = vbt.IndicatorFactory.from_talib('CDLEVENINGSTAR').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # 'Evening star'
candle_sell_signal_3 = vbt.IndicatorFactory.from_talib('CDL3BLACKCROWS').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # '3 Black Crows'
candle_buy_sell_signal_1 = vbt.IndicatorFactory.from_talib('CDLENGULFING').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # 'Engulfing: Bullish (buy) / Bearish (sell)'
candle_buy_sell_signal_2 = vbt.IndicatorFactory.from_talib('CDL3OUTSIDE').run(
open_prices, high_prices, low_prices, close_prices).integer.to_numpy() # 'Three Outside: Up (buy) / Down (sell)'
SuperAI_signal = create_signal(open_prices, high_prices, low_prices, close_prices, volume,
buylesstime, selltime,
ma, ma_fast, ma_slow,
macd, macd_diff, macd_sign,
rsi, rsi_entry, rsi_exit,
stoch, stoch_signal, stoch_entry, stoch_exit,
bb_low, bb_high,
mfi, mfi_entry, mfi_exit,
candle_buy_signal_1, candle_buy_signal_2, candle_buy_signal_3,
candle_sell_signal_1, candle_sell_signal_2, candle_sell_signal_3,
candle_buy_sell_signal_1, candle_buy_sell_signal_2)
return SuperAI_signal
parameters_names = ["ma_window", "ma_fast_window", "ma_slow_window",
"macd_slow_window", "macd_fast_window", "macd_sign_window",
"rsi_window", "rsi_entry", "rsi_exit",
"stoch_window", "stoch_smooth_window", "stoch_entry", "stoch_exit",
"bb_window", "bb_dev",
"mfi_window", "mfi_entry", "mfi_exit"]
SuperAI_Ind = vbt.IndicatorFactory(
class_name = "SuperAI_Ind",
short_name = "SuperInd",
input_names = ["open", "high", "low", "close", "volume", "buylesstime", "selltime"],
param_names = parameters_names,
output_names = ["output"]).from_apply_func(superai_signals,
ma_window = ma_timeframe,
ma_fast_window = ma_fast_timeframe,
ma_slow_window = ma_slow_timeframe,
macd_slow_window = macd_slow_timeframe,
macd_fast_window = macd_fast_timeframe,
macd_sign_window = macd_signal_timeframe,
rsi_window = rsi_timeframe,
rsi_entry = rsi_oversold_threshold,
rsi_exit = rsi_overbought_threshold,
stoch_window = stoch_timeframe,
stoch_smooth_window = stoch_smooth_timeframe,
stoch_entry = stoch_oversold_threshold,
stoch_exit = stoch_overbought_threshold,
bb_window = bb_timeframe,
bb_dev = bb_dev,
mfi_window = mfi_timeframe,
mfi_entry = mfi_oversold_threshold,
mfi_exit = mfi_overbought_threshold)
open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime = prepare_data(data_start, data_end)
trading_signals = SuperAI_Ind.run(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime,
ma_window = ma_timeframe,
ma_fast_window = ma_fast_timeframe,
ma_slow_window = ma_slow_timeframe,
macd_slow_window = macd_slow_timeframe,
macd_fast_window = macd_fast_timeframe,
macd_sign_window = macd_signal_timeframe,
rsi_window = rsi_timeframe,
rsi_entry = rsi_oversold_threshold,
rsi_exit= rsi_overbought_threshold,
stoch_window = stoch_timeframe,
stoch_smooth_window = stoch_smooth_timeframe,
stoch_entry = stoch_oversold_threshold,
stoch_exit = stoch_overbought_threshold,
bb_window = bb_timeframe,
bb_dev = bb_dev,
mfi_window = mfi_timeframe,
mfi_entry = mfi_oversold_threshold,
mfi_exit= mfi_overbought_threshold,
param_product = True)
print(trading_signals.output.to_string())
entries = trading_signals.output == 1.0
exits = trading_signals.output == -1.0
SuperAI_portfolio = vbt.Portfolio.from_signals(close_prices,
entries,
exits,
init_cash = 100000,
tp_stop = take_profit_percent,
sl_stop = stop_loss_percent,
fees = 0.00)
returns = SuperAI_portfolio.total_return() * 100
returns
SuperAI_portfolio.plot()
SuperAI_portfolio.stats()
trading_signals = SuperAI_Ind.run(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime,
ma_window = np.arange(14, 30, step=14, dtype=int), #[14, 28]
ma_fast_window = np.arange(14, 22, step=7, dtype=int), #[14, 21]
ma_slow_window = np.arange(30, 51, step=20, dtype=int), #[30, 50]
macd_slow_window = np.arange(26, 27, step=100, dtype=int), #[26]
macd_fast_window = np.arange(12, 13, step=100, dtype=int), #[12]
macd_sign_window = np.arange(9, 10, step=100, dtype=int), #[9]
rsi_window = np.arange(14, 22, step=7, dtype=int), #[14, 21]
rsi_entry = np.arange(20, 31, step=10, dtype=int), #[20, 30]
rsi_exit= np.arange(70, 81, step=10, dtype=int), #[70, 80]
stoch_window = np.arange(14, 15, step=100, dtype=int), #[14]
stoch_smooth_window = np.arange(3, 4, step=100, dtype=int), #[3]
stoch_entry = np.arange(20, 21, step=100, dtype=int), #[20]
stoch_exit= np.arange(80, 81, step=100, dtype=int), #[80]
bb_window = np.arange(10, 21, step=10, dtype=int), #[10, 20]
bb_dev = np.arange(2, 3, step=100, dtype=int), #[2]
mfi_window = np.arange(14, 22, step=7, dtype=int), #[14, 21]
mfi_entry = np.arange(10, 21, step=10, dtype=int), #[10, 20]
mfi_exit= np.arange(80, 91, step=10, dtype=int), #[80, 90]
param_product = True)
entries = trading_signals.output == 1.0
exits = trading_signals.output == -1.0
SuperAI_portfolio = vbt.Portfolio.from_signals(close_prices,
entries,
exits,
init_cash = 100000,
tp_stop = take_profit_percent,
sl_stop = stop_loss_percent,
fees = 0.00)
returns = SuperAI_portfolio.total_return() * 100
SuperAI_portfolio.stats()
returns
returns.max()
max_dd = SuperAI_portfolio.max_drawdown()
max_dd.max()
sharpe_ratio = SuperAI_portfolio.sharpe_ratio(freq='m')
sharpe_ratio.max()
returns.idxmax()
max_dd.idxmax()
sharpe_ratio.idxmax()
(ma_window_max, ma_fast_window_max, ma_slow_window_max,
macd_slow_window_max, macd_fast_window_max, macd_sign_window_max,
rsi_window_max, rsi_entry_max, rsi_exit_max,
stoch_window_max, stoch_smooth_window_max, stoch_entry_max, stoch_exit_max,
bb_window_max, bb_dev_max, mfi_window_max,
mfi_entry_max, mfi_exit_max) = returns.idxmax() #max_dd.idxmax() #sharpe_ratio.idxmax()
(ma_window_max, ma_fast_window_max, ma_slow_window_max,
macd_slow_window_max, macd_fast_window_max, macd_sign_window_max,
rsi_window_max, rsi_entry_max, rsi_exit_max,
stoch_window_max, stoch_smooth_window_max, stoch_entry_max, stoch_exit_max,
bb_window_max, bb_dev_max, mfi_window_max,
mfi_entry_max, mfi_exit_max)
trading_signals = SuperAI_Ind.run(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime,
ma_window = ma_window_max,
ma_fast_window = ma_fast_window_max,
ma_slow_window = ma_slow_window_max,
macd_slow_window = macd_slow_window_max,
macd_fast_window = macd_fast_window_max,
macd_sign_window = macd_sign_window_max,
rsi_window = rsi_window_max,
rsi_entry = rsi_entry_max,
rsi_exit= rsi_exit_max,
stoch_window = stoch_window_max,
stoch_smooth_window = stoch_smooth_window_max,
stoch_entry = stoch_entry_max,
stoch_exit = stoch_exit_max,
bb_window = bb_window_max,
bb_dev = bb_dev_max,
mfi_window = mfi_window_max,
mfi_entry = mfi_entry_max,
mfi_exit= mfi_exit_max,
param_product = True)
entries = trading_signals.output == 1.0
exits = trading_signals.output == -1.0
SuperAI_portfolio = vbt.Portfolio.from_signals(close_prices,
entries,
exits,
init_cash = 100000,
tp_stop = take_profit_percent,
sl_stop = stop_loss_percent,
fees = 0.00)
returns = SuperAI_portfolio.total_return() * 100
returns
SuperAI_portfolio.stats()
SuperAI_portfolio.plot()
open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime = prepare_data('2022-06-06', '2022-06-07')
trading_signals = SuperAI_Ind.run(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime,
ma_window = ma_window_max,
ma_fast_window = ma_fast_window_max,
ma_slow_window = ma_slow_window_max,
macd_slow_window = macd_slow_window_max,
macd_fast_window = macd_fast_window_max,
macd_sign_window = macd_sign_window_max,
rsi_window = rsi_window_max,
rsi_entry = rsi_entry_max,
rsi_exit= rsi_exit_max,
stoch_window = stoch_window_max,
stoch_smooth_window = stoch_smooth_window_max,
stoch_entry = stoch_entry_max,
stoch_exit = stoch_exit_max,
bb_window = bb_window_max,
bb_dev = bb_dev_max,
mfi_window = mfi_window_max,
mfi_entry = mfi_entry_max,
mfi_exit= mfi_exit_max,
param_product = True)
entries = trading_signals.output == 1.0
exits = trading_signals.output == -1.0
SuperAI_portfolio = vbt.Portfolio.from_signals(close_prices,
entries,
exits,
init_cash = 100000,
tp_stop = take_profit_percent,
sl_stop = stop_loss_percent,
fees = 0.00)
SuperAI_portfolio.stats()
SuperAI_portfolio.plot()
In the cell below you can choose what percentage of the cash you have in your paper trading account should be used.
Simply type the number between 0 and 100 and the bot will calculate how much money that is.
#SuperAI Trading Bot
funds_percentage = 95 #replace it with the percentage of the amount of money you have to use for trading
As said previously, this bot will calculate how much funds should it invest based on the amount of money you have in your Alpaca paper trading account.
The funds will be calculated every time before buying stocks.
At first we get info from Alpaca about our account (we get all the money we have, all the positions, etc.) and declare how big our funds to trade should be.
We also have here some print statements that will show us what we have in the next line.
#SuperAI Trading Bot
account = api.get_account()
cash = float(account.cash)
buying_power = float(account.buying_power)
funds = cash * funds_percentage / 100
print("We have {:.2f}$ cash.".format(cash))
print("Our Buying Power is: {:.2f}$".format(buying_power))
print("Funds we will use for trading: {:.2f}$".format(funds))
The bot can autmatically sell the shares you have to take profit when the price reaches declared level.
If you want to use this functionality, the 'take_profit_automatically' should be set to 'True'. If you don't want to use this functionality, change that value to 'False'.
#SuperAI Trading Bot
take_profit_automatically = True #change to False if you don't want to use take_profit function
Now, we create a function to take profit.
In this function, at first we check if we declared that we want to use it. And if so, we check if we have any shares in our portfolio.
Then, we check if there is no other order already created. Because we will be using this function in real time, sometimes there might be already an order filled, but not yet executed and this checking helps us avoid problems with creating too many orders for one set of shares.
We take profit (sell) when the last close price is at least as big as the previously declared (calculated by multiplying the average entry price times the percent we declared).
We also create here some print statements, so we know what's going in real time.
#SuperAI Trading Bot
profit_ratio = 100 + (take_profit_percent * 100)
#SuperAI Trading Bot
def take_profit(close_price, sell_order_filled):
if take_profit_automatically == True:
try:
position = api.get_position(asset)
aep = float(api.get_position(asset).avg_entry_price)
if sell_order_filled == False:
if close_price >= aep * profit_ratio / 100:
n_shares = float(position.qty)
api.submit_order(symbol=asset,qty=n_shares,side='sell',type='market',time_in_force='gtc')
print("Take profit price is {}% from {:.2f}$ we paid for 1 {} = {:.2f}$. "
.format(profit_ratio, aep, asset, aep * profit_ratio / 100))
print('The current {:.2f}$ is good enough. We take profit with an order to sell {} shares of {}.'
.format(close_price, n_shares, asset))
else:
print('Take profit price is {}% from {:.2f}$ we paid for 1 {} = {:.2f}.'
.format(profit_ratio, aep, asset, aep * profit_ratio / 100))
print('Last close price {:.2f}$ is not enough.'.format(close_price))
except:
pass
print()
else:
pass
The bot can also autmatically sell the shares you have to stop loss when the price reaches declared level.
Here you can declare if you want to use this functionality, and what the price should be.
#SuperAI Trading Bot
stop_loss_automatically = True #change to False if you don't want to use stop_loss function
We use the same logic as in the take_profit function in stop loss function.
#SuperAI Trading Bot
stoploss_ratio = 100 - (stop_loss_percent * 100)
#SuperAI Trading Bot
def stop_loss(close_price, sell_order_filled):
if stop_loss_automatically == True:
try:
position = api.get_position(asset)
aep = float(api.get_position(asset).avg_entry_price)
if sell_order_filled == False:
if close_price < aep * stoploss_ratio / 100:
n_shares = float(position.qty)
api.submit_order(symbol=asset,qty=n_shares,side='sell',type='market',time_in_force='gtc')
print("Stop loss price is {}% from {:.2f}$ we paid for 1 {} = {:.2f}$."
.format(stoploss_ratio, aep, asset, aep * stoploss_ratio / 100))
print('The current {:.2f}$ is less. We stop loss with an order to sell {} shares of {}.'
.format(close_price, n_shares, asset))
else:
print("Stop loss price is {}% from {:.2f}$ we paid for 1 {} = {:.2f}$."
.format(stoploss_ratio, aep, asset, aep * stoploss_ratio / 100))
print("Last close price {:.2f}$ is not that low.".format(close_price))
except:
pass
print()
else:
pass
In the on_message function we'll be using the parameters we calculated during our backtesting. Here we can see them one more time.
#SuperAI Trading Bot
def cal_tech_ind(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime):
#CALCULATING TECHNICAL INDICATORS SIGNALS
close_price = close_prices[-1]
#Calculating MA Signals
try:
ma = ta.trend.ema_indicator(close_prices, window = ma_window_max)
ma = np.round(ma, 2)
ma_last = float(ma.iloc[-1])
ma_fast = ta.trend.ema_indicator(close_prices, window = ma_fast_window_max)
ma_fast = np.round(ma_fast, 2)
ma_fast_last = float(ma_fast.iloc[-1])
ma_slow = ta.trend.ema_indicator(close_prices, window = ma_slow_window_max)
ma_slow = np.round(ma_slow, 2)
ma_slow_last = float(ma_slow.iloc[-1])
print("Last MA is: {:.3f}. Last Fast MA is: {:.3f}. Last Slow MA is: {:.3f}.\n".format(ma_last,
ma_fast_last, ma_slow_last))
except:
print ("MA signal doesn't work.\n")
#Calculating MACD Signal
try:
macd = ta.trend.macd(close_prices, window_slow = macd_slow_window_max, window_fast = macd_fast_window_max)
macd = np.round(macd, 2)
macd_last = float(macd.iloc[-1])
macd_diff = ta.trend.macd_diff(close_prices, window_slow = macd_slow_window_max,
window_fast = macd_fast_window_max, window_sign = macd_sign_window_max)
macd_diff = np.round(macd_diff, 2)
macd_diff_last = float(macd_diff.iloc[-1])
macd_sign = ta.trend.macd_signal(close_prices, window_slow = macd_slow_window_max,
window_fast = macd_fast_window_max, window_sign = macd_sign_window_max)
macd_sign = np.round(macd_sign, 2)
macd_sign_last = float(macd_sign.iloc[-1])
print("Last MACD is: {:.3f}. Last MACD_DIFF is: {:.3f}. Last MACD_SIGNAL is: {:.3f}.\n".format(macd_last,
macd_diff_last, macd_sign_last))
except:
print ("MACD signal doesn't work.\n")
#Calculating RSI Signal
try:
rsi = ta.momentum.rsi(close_prices, window = rsi_window_max)
rsi = np.round(rsi, 2)
rsi_last = rsi.iloc[-1]
rsi_entry = rsi_entry_max
rsi_exit = rsi_exit_max
print("Last RSI is {:.3f}. RSI thresholds are: {:.2f} - {:.2f}.\n".format(rsi_last, rsi_entry, rsi_exit))
except:
print("RSI signal doesn't work.\n")
#Calculating Stochastic Signal
try:
stoch = ta.momentum.stoch(high_prices, low_prices, close_prices,
window = stoch_window_max, smooth_window = stoch_smooth_window_max)
stoch = np.round(stoch, 2)
stoch_last = stoch.iloc[-1]
stoch_sign = ta.momentum.stoch_signal(high_prices, low_prices, close_prices,
window = stoch_window_max, smooth_window = stoch_smooth_window_max)
stoch = np.round(stoch_sign, 2)
stoch_sign_last = stoch_sign.iloc[-1]
stoch_entry = stoch_entry_max
stoch_exit = stoch_exit_max
print("Last Stochastic is {:.3f}. Stochastic thresholds are: {:.2f} - {:.2f}.\n".format(
stoch_last, stoch_entry, stoch_exit))
print("Last Stochastic Signal is {:.3f}. Stochastic thresholds are: {:.2f} - {:.2f}.\n".format(
stoch_sign_last, stoch_entry, stoch_exit))
except:
print("Stochastic signal doesn't work.\n")
#Calculating Bollinger Bands Signal
try:
bb_low = ta.volatility.bollinger_lband(close_prices, window=bb_window_max, window_dev = bb_dev_max)
bb_low = np.round(bb_low, 2)
bb_high = ta.volatility.bollinger_hband(close_prices, window=bb_window_max, window_dev = bb_dev_max)
bb_high = np.round(bb_high, 2)
bb_low_last = float(bb_low.iloc[-1])
bb_high_last = float(bb_high.iloc[-1])
print("Last price is: {}$. Bollinger Bands are: Lower: {:.3f}, Upper: {:.3f}.\n".format(close_price,
bb_low_last, bb_high_last))
except:
print ("Bollinger Bands signal doesn't work.\n")
#Calculating MFI Signal
try:
mfi = ta.volume.money_flow_index(high_prices, low_prices, close_prices, volume, window = mfi_window_max)
mfi = np.round(mfi, 2)
mfi_last = mfi.iloc[-1]
mfi_entry = mfi_entry_max
mfi_exit = mfi_exit_max
print("Last MFI is {:.3f}. MFI thresholds are: {:.2f} - {:.2f}.\n".format(mfi_last, mfi_entry, mfi_exit))
except:
print("MFI signal doesn't work.\n")
return (ma, ma_fast, ma_slow,
macd, macd_diff, macd_sign,
rsi, rsi_entry, rsi_exit,
stoch, stoch_sign, stoch_entry, stoch_exit,
bb_low, bb_high,
mfi, mfi_entry, mfi_exit)
#SuperAI Trading Bot
def cal_can_pat(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime):
#CALCULATING CANDLESTICK PATTERNS AND SIGNALS
#Hammer
candle_buy_signal_1 = ta_lib.CDLHAMMER(open_prices, high_prices, low_prices, close_prices)
last_candle_buy_signal_1 = candle_buy_signal_1.iloc[-1]
print("Last Candle Buy Signal 1: {}.".format(last_candle_buy_signal_1))
#Morning Star
candle_buy_signal_2 = ta_lib.CDLMORNINGSTAR(open_prices, high_prices, low_prices, close_prices)
last_candle_buy_signal_2 = candle_buy_signal_2.iloc[-1]
print("Last Candle Buy Signal 2: {}.".format(last_candle_buy_signal_2))
#Three White Soldiers
candle_buy_signal_3 = ta_lib.CDL3WHITESOLDIERS(open_prices, high_prices, low_prices, close_prices)
last_candle_buy_signal_3 = candle_buy_signal_3.iloc[-1]
print("Last Candle Buy Signal 3: {}.".format(last_candle_buy_signal_3))
#Shooting Star
candle_sell_signal_1 = ta_lib.CDLSHOOTINGSTAR(open_prices, high_prices, low_prices, close_prices)
last_candle_sell_signal_1 = candle_sell_signal_1.iloc[-1]
print("Last Candle Sell Signal 1: {}.".format(last_candle_sell_signal_1))
#Evening Star
candle_sell_signal_2 = ta_lib.CDLEVENINGSTAR(open_prices, high_prices, low_prices, close_prices)
last_candle_sell_signal_2 = candle_sell_signal_2.iloc[-1]
print("Last Candle Sell Signal 2: {}.".format(last_candle_sell_signal_2))
#3 Black Crows
candle_sell_signal_3 = ta_lib.CDL3BLACKCROWS(open_prices, high_prices, low_prices, close_prices)
last_candle_sell_signal_3 = candle_sell_signal_3.iloc[-1]
print("Last Candle Sell Signal 3: {}.".format(last_candle_sell_signal_3))
#Engulfing (Bullish (buy) / Bearish (Sell))
candle_buy_sell_signal_1 = ta_lib.CDLENGULFING(open_prices, high_prices, low_prices, close_prices)
last_candle_buy_sell_signal_1 = candle_buy_sell_signal_1.iloc[-1]
print("Last Candle Buy Sell Signal 1: {}.".format(last_candle_buy_sell_signal_1))
#Three Outside: Up (buy) / Down (sell)
candle_buy_sell_signal_2 = ta_lib.CDL3OUTSIDE(open_prices, high_prices, low_prices, close_prices)
last_candle_buy_sell_signal_2 = candle_buy_sell_signal_2.iloc[-1]
print("Last Candle Buy Sell Signal 2: {}.".format(last_candle_buy_sell_signal_2))
return (candle_buy_signal_1, candle_buy_signal_2, candle_buy_signal_3,
candle_sell_signal_1, candle_sell_signal_2, candle_sell_signal_3,
candle_buy_sell_signal_1, candle_buy_sell_signal_2)
#SuperAI Trading Bot
def check_if_market_open():
if api.get_clock().is_open == False:
print("The market is closed at the moment.")
print("Time to open is around: {:.0f} minutes. So I'll stop working for now. Hope you don't mind."
.format((api.get_clock().next_open.timestamp()- api.get_clock().timestamp.timestamp())/60))
sys.exit("I'm out. Turn me back on when it's time. Yours, SuperAI trader.")
else:
pass
#SuperAI Trading Bot
buyless1_start = datetime.time(int(buyless_time_start_1[:2]), int(buyless_time_start_1[3:]))
buyless1_end = datetime.time(int(buyless_time_end_1[:2]), int(buyless_time_end_1[3:]))
buyless2_start = datetime.time(int(buyless_time_start_2[:2]), int(buyless_time_start_2[3:]))
buyless2_end = datetime.time(int(buyless_time_end_2[:2]), int(buyless_time_end_2[3:]))
sell_time_start = datetime.time(int(selltime_start[:2]), int(selltime_start[3:]))
sell_time_end = datetime.time(int(selltime_end[:2]), int(selltime_end[3:]))
#SuperAI Trading Bot
def buyless_time(time_now):
buylesstime = (buyless1_start < time_now < buyless1_end) | (buyless2_start < time_now < buyless2_end)
return buylesstime
#SuperAI Trading Bot
def sell_time(time_now):
selltime = (sell_time_start < time_now < sell_time_end)
return selltime
#SuperAI Trading Bot
#check for more: https://alpaca.markets/learn/code-cryptocurrency-live-trading-bot-python-alpaca/
def wait_for_bar_to_close():
time_now = datetime.datetime.now()
next_min = time_now.replace(second=5, microsecond=0) + timedelta(minutes=1)
pause = math.ceil((next_min - time_now).seconds)
print("I'll wait {} seconds for the bar to close.".format(pause))
print("\n* * * * * * * * * * * * * * * * * * * * * * * * *\n")
return pause
#SuperAI Trading Bot
def on_open():
print("I'm connected to Alpaca API and ready to work. I'm starting to watch the prices.\n")
cash = float(api.get_account().cash)
print("We have {:.2f}$ cash.".format(cash))
try:
position = api.get_position(asset)
n_shares = float(position.qty)
print("We have {} shares of {}.\n".format(n_shares, asset))
except:
print("We don't have any shares of {} at the moment.\n".format(asset))
funds = cash * funds_percentage / 100
print("Funds we will use for trading: {:.2f}$.\n".format(funds))
print("I will be trading {}.\n".format(asset))
if take_profit_automatically:
print("Take profit is set to +{}% from the average entry price.".format(take_profit_percent*100))
print("I will be trading when the technical indicators and candlestick patterns say so, but also")
print("if entry price is e.g. 100$ I'll automatically sell when last close price is more than 100$+{}%*100$={:.2f}$"
.format(take_profit_percent * 100, 100*profit_ratio/100))
else:
print("Take profit automatically is turned off.")
print("I will use technical indicators and candlestick patterns to get as much profit as I can.")
if stop_loss_automatically:
print("\nStop loss is set to -{}% from the average entry price.".format(stop_loss_percent*100))
print("I will be trading when the technical indicators and candlestick patterns say so, but also")
print("if entry price is e.g. 100$ I'll automatically sell when last close price is less than 100$-{}%*100$={:.2f}$"
.format(stop_loss_percent * 100, 100*stoploss_ratio/100))
else:
print("\nStop loss automatically is turned off.")
print("I will use technical indicators and candlestick patterns so I don't lose money.")
print("\nSo, here we go. Wish me luck.\n")
print("* * * * * * * * * * * * * * * * * * * * * * * * *\n")
global trading_hour_start, trading_hour_stop
global buyless_time_start_1, buyless_time_end_1, buyless_time_start_2, buyless_time_end_2
global selltime_start, selltime_end
(trading_hour_start, trading_hour_stop,
buyless_time_start_1, buyless_time_end_1, buyless_time_start_2, buyless_time_end_2,
selltime_start, selltime_end) = trading_buy_sell_time()
if asset_type == "stock":
check_if_market_open()
#SuperAI Trading Bot
def on_message():
nyc_datetime = api.get_clock().timestamp.tz_convert('America/New_York')
print("New York time:", str(nyc_datetime)[:16])
open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime = prepare_data(
str(datetime.date.today() - datetime.timedelta(days = 2)),
str(datetime.date.today() + datetime.timedelta(days = 2)))
close_price = close_prices[-1]
print("Close price of {}: {:.2f}$\n".format(asset, close_price))
try:
position = api.get_position(asset)
n_shares = float(position.qty)
print("We have {} shares of {}.\n".format(n_shares, asset))
except:
print("We don't have any shares of {} at the moment.\n".format(asset))
cash = float(api.get_account().cash)
print("We have {:.2f}$ cash.".format(cash))
funds = cash * funds_percentage / 100
print("Funds we will use for trading: {:.2f}$.\n".format(funds))
#CALCULATING TECHNICAL INDICATORS SIGNALS
(ma, ma_fast, ma_slow, macd, macd_diff, macd_sign, rsi, rsi_entry, rsi_exit,
stoch, stoch_sign, stoch_entry, stoch_exit,
bb_low, bb_high, mfi, mfi_entry, mfi_exit) = cal_tech_ind(
open_prices, high_prices, low_prices, close_prices, volume,
buylesstime, selltime)
#CALCULATING CANDLESTICK PATTERNS AND SIGNALS
(candle_buy_signal_1, candle_buy_signal_2, candle_buy_signal_3,
candle_sell_signal_1, candle_sell_signal_2, candle_sell_signal_3,
candle_buy_sell_signal_1, candle_buy_sell_signal_2) = cal_can_pat(
open_prices, high_prices, low_prices, close_prices, volume,
buylesstime, selltime)
#Calculate final trade signal
try:
final_trade_signals = create_signal(open_prices, high_prices, low_prices, close_prices, volume,
buylesstime, selltime,
ma, ma_fast, ma_slow,
macd, macd_diff, macd_sign,
rsi, rsi_entry, rsi_exit,
stoch, stoch_sign, stoch_entry, stoch_exit,
bb_low, bb_high,
mfi, mfi_entry, mfi_exit,
candle_buy_signal_1, candle_buy_signal_2, candle_buy_signal_3,
candle_sell_signal_1, candle_sell_signal_2, candle_sell_signal_3,
candle_buy_sell_signal_1, candle_buy_sell_signal_2)
final_trade_signal = final_trade_signals[-1]
if final_trade_signal == 0:
print("\nFinal trade signal is: DO NOTHING\n")
elif final_trade_signal == 1:
print("\nFinal trade signal is: BUY\n")
elif final_trade_signal == -1:
print("\nFinal trade signal is: SELL\n")
except:
print("\nFinal trade signal doesn't work.\n")
final_trade_signal = False
#Execute action after recieving the final trade signal: submitting an order
sell_order_filled = False
if final_trade_signal == 1: #"buy":
try:
api.get_position(asset)
print("We hit the threshold to buy, but we already have some shares, so we won't buy more.\n")
except:
cash = float(api.get_account().cash)
n_shares = np.round(funds // close_price)
if asset_type == 'crypto':
n_shares = np.round(funds / close_price, int(rounding))
api.submit_order(symbol=asset,qty=n_shares,side="buy",type="market",time_in_force="gtc")
print('We submitted the order to buy {} {} shares.'.format(n_shares, asset))
elif final_trade_signal == -1: #"sell":
try:
position = api.get_position(asset)
n_shares = float(position.qty)
api.submit_order(symbol=asset,qty=n_shares,side='sell',type='market',time_in_force='gtc')
sell_order_filled = True
print('We submitted an order to sell {} {} shares.'.format(n_shares, asset))
except:
print("We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n")
else:
print("The signal was inconclusive - probably indicators showed us we should wait, so we wait.\n")
#Hand-made take profit
take_profit(close_price, sell_order_filled)
#Hand-made stop loss
stop_loss(close_price, sell_order_filled)
print("\n* * * * * * * * * * * * * * * * * * * * * * * * *\n")
if asset_type == "stock":
check_if_market_open()
#SuperAI Trading Bot
def SuperAI_Trading_Bot():
on_open()
time.sleep(wait_for_bar_to_close())
while True:
on_message()
time.sleep(wait_for_bar_to_close())
print("You've interrupted me. That's it then. I hope I did good. Till the next time.")
And now we have all we need. Now we can run the bot.
So, here we go!
#SuperAI Trading Bot
SuperAI_Trading_Bot()
if you want to trade stocks replace it with the ticker of the company you prefer: https://www.nyse.com/listings_directory/stock
data_source can be 'Alpaca' or 'Yahoo'
#SuperAI Trading Bot
(asset, asset_type, data_source) = ("AAPL", "stock", "Yahoo")
SuperAI_Trading_Bot()
if you want to trade crypto check: https://alpaca.markets/support/what-cryptocurrencies-does-alpaca-currently-support/
rounding declares the number of numbers after comma for orders
According to Alpaca: "All cryptocurrency assets are fractionable but the supported decimal points vary depending on the cryptocurrency."
Check the smallest qty of the crypto you want to trade before declaring the 'rounding'
read more about minimum qty and qty increment at https://alpaca.markets/docs/trading/crypto-trading/
Minimum quantity of crypto to buy may differ, so you should choose rounding wisely.
E.g.:
#SuperAI Trading Bot
(asset, asset_type, rounding) = ("ETHUSD", "crypto", 3)
SuperAI_Trading_Bot()
#SuperAI Trading Bot
#(asset, asset_type, rounding) = ("BTCUSD", "crypto", 0)
(asset, asset_type, data_source) = ("AAPL", "stock", "Alpaca")
ma_timeframe = 28
ma_fast_timeframe = 14
ma_slow_timeframe = 50
macd_slow_timeframe = 26
macd_fast_timeframe = 12
macd_signal_timeframe = 9
rsi_timeframe = 14
rsi_oversold_threshold = 30
rsi_overbought_threshold = 70
stoch_timeframe = 14
stoch_smooth_timeframe = 3
stoch_oversold_threshold = 20
stoch_overbought_threshold = 80
bb_timeframe = 10
bb_dev = 2
mfi_timeframe = 14
mfi_oversold_threshold = 20
mfi_overbought_threshold = 80
#SuperAI Trading Bot
#@njit #you can unhash it if you have numba installed and imported and the bot should work a little faster, if you use njit
def create_signal(open_prices, high_prices, low_prices, close_prices, volume,
buylesstime, selltime, #Time to abstain from buying and forced selling
ma, ma_fast, ma_slow, #Moving Average
macd, macd_diff, macd_sign, #Moving Average Convergence Divergence
rsi, rsi_entry, rsi_exit, #Relative Strength Index
stoch, stoch_signal, stoch_entry, stoch_exit, #Stochastic
bb_low, bb_high, #Bollinger Bands
mfi, mfi_entry, mfi_exit, #Money Flow Index
candle_buy_signal_1, candle_buy_signal_2, candle_buy_signal_3, #Candle signals to buy
candle_sell_signal_1, candle_sell_signal_2, candle_sell_signal_3, #Candle signals to sell
candle_buy_sell_signal_1, candle_buy_sell_signal_2): #Candle signals to buy or sell
SuperAI_signal_buy = np.where(
(buylesstime != 1)
&
(
(
((ma_fast < ma_slow) & (rsi < rsi_entry))
|
(close_prices < bb_low)
|
(mfi < mfi_entry)
|
(close_prices > ma)
|
(macd < 0)
|
(macd_diff < 0)
|
(macd_sign < macd)
|
(stoch < stoch_entry)
|
(stoch_signal < stoch_entry)
|
((close_prices > ma) & (ma_fast > ma_slow))
|
(((rsi < rsi_entry) & ((close_prices < ma) | (macd < 0))))
|
((close_prices > ma) & (shifted(close_prices, 1) < ma))
|
((stoch < stoch_entry) & (
(ma > (shifted(ma, 1))) &
(shifted(ma, 1) > (shifted(ma, 2)))))
|
((rsi < rsi_entry) & (
~((ma > (shifted(ma, 2) * 1.01)) &
(shifted(ma, 2) > (shifted(ma, 4)*1.01)))))
)
|
((candle_buy_signal_1 > 0) | (candle_buy_signal_2 > 0) | (candle_buy_signal_3 > 0)
| (candle_buy_sell_signal_1 > 0) | (candle_buy_sell_signal_2 > 0))
)
, 1, 0) #1 is buy, -1 is sell, 0 is do nothing
SuperAI_signal = np.where(
(selltime == 1)
|
(ma_fast > ma_slow)
|
(rsi > rsi_exit)
|
(close_prices > bb_high)
|
(mfi > mfi_exit)
|
(close_prices < ma)
|
(macd_diff > 0)
|
(macd_sign > macd)
|
(stoch > stoch_exit)
|
(stoch_signal > stoch_exit)
|
((close_prices < ma) & (rsi > rsi_exit))
|
(((rsi > rsi_exit) & ((close_prices < ma) | (macd > 3))))
|
((close_prices < ma) & (shifted(close_prices, 1) > ma))
|
((stoch > stoch_exit) & (
(ma > (shifted(ma, 1))) &
(shifted(ma, 1) > (shifted(ma, 2)))))
|
((candle_sell_signal_1 < 0) | (candle_sell_signal_2 < 0) | (candle_buy_signal_3 < 0)
| (candle_buy_sell_signal_1 < 0) | (candle_buy_sell_signal_2 < 0))
, -1, SuperAI_signal_buy) #1 is buy, -1 is sell, 0 is do nothing
return SuperAI_signal
open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime = prepare_data('2022-05-30', '2022-06-06')
trading_signals = SuperAI_Ind.run(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime,
ma_window = ma_timeframe,
ma_fast_window = ma_fast_timeframe,
ma_slow_window = ma_slow_timeframe,
macd_slow_window = macd_slow_timeframe,
macd_fast_window = macd_fast_timeframe,
macd_sign_window = macd_signal_timeframe,
rsi_window = rsi_timeframe,
rsi_entry = rsi_oversold_threshold,
rsi_exit= rsi_overbought_threshold,
stoch_window = stoch_timeframe,
stoch_smooth_window = stoch_smooth_timeframe,
stoch_entry = stoch_oversold_threshold,
stoch_exit = stoch_overbought_threshold,
bb_window = bb_timeframe,
bb_dev = bb_dev,
mfi_window = mfi_timeframe,
mfi_entry = mfi_oversold_threshold,
mfi_exit= mfi_overbought_threshold,
param_product = True)
entries = trading_signals.output == 1.0
exits = trading_signals.output == -1.0
SuperAI_portfolio = vbt.Portfolio.from_signals(close_prices,
entries,
exits,
init_cash = 100000,
#tp_stop = take_profit_percent,
#sl_stop = stop_loss_percent,
fees = 0.00)
SuperAI_portfolio.stats()
SuperAI_portfolio.plot()
#SuperAI Trading Bot
#@njit #you can unhash it if you have numba installed and imported and the bot should work a little faster, if you use njit
def create_signal(open_prices, high_prices, low_prices, close_prices, volume,
buylesstime, selltime, #Time to abstain from buying and forced selling
ma, ma_fast, ma_slow, #Moving Average
macd, macd_diff, macd_sign, #Moving Average Convergence Divergence
rsi, rsi_entry, rsi_exit, #Relative Strength Index
stoch, stoch_signal, stoch_entry, stoch_exit, #Stochastic
bb_low, bb_high, #Bollinger Bands
mfi, mfi_entry, mfi_exit, #Money Flow Index
candle_buy_signal_1, candle_buy_signal_2, candle_buy_signal_3, #Candle signals to buy
candle_sell_signal_1, candle_sell_signal_2, candle_sell_signal_3, #Candle signals to sell
candle_buy_sell_signal_1, candle_buy_sell_signal_2): #Candle signals to buy or sell
SuperAI_signal_buy = np.where(
(buylesstime != 1)
&
((macd < 0) & (macd > macd_sign) & (shifted(macd, 1) <= shifted(macd_sign, 1)))
&
((ma > (shifted(ma, 2))) &
(shifted(ma, 2) > (shifted(ma, 4))))
, 1, 0) #1 is buy, -1 is sell, 0 is do nothing
SuperAI_signal = np.where(
(selltime == 1)
|
((stoch > stoch_exit) & (rsi > rsi_exit))
|
((close_prices > bb_high) & (mfi > mfi_exit))
, -1, SuperAI_signal_buy) #1 is buy, -1 is sell, 0 is do nothing
return SuperAI_signal
open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime = prepare_data('2022-05-01', '2022-06-06')
trading_signals = SuperAI_Ind.run(open_prices, high_prices, low_prices, close_prices, volume, buylesstime, selltime,
ma_window = ma_timeframe,
ma_fast_window = ma_fast_timeframe,
ma_slow_window = ma_slow_timeframe,
macd_slow_window = macd_slow_timeframe,
macd_fast_window = macd_fast_timeframe,
macd_sign_window = macd_signal_timeframe,
rsi_window = rsi_timeframe,
rsi_entry = rsi_oversold_threshold,
rsi_exit= rsi_overbought_threshold,
stoch_window = stoch_timeframe,
stoch_smooth_window = stoch_smooth_timeframe,
stoch_entry = stoch_oversold_threshold,
stoch_exit = stoch_overbought_threshold,
bb_window = bb_timeframe,
bb_dev = bb_dev,
mfi_window = mfi_timeframe,
mfi_entry = mfi_oversold_threshold,
mfi_exit= mfi_overbought_threshold,
param_product = True)
entries = trading_signals.output == 1.0
exits = trading_signals.output == -1.0
SuperAI_portfolio = vbt.Portfolio.from_signals(close_prices,
entries,
exits,
init_cash = 100000,
#tp_stop = take_profit_percent,
#sl_stop = stop_loss_percent,
fees = 0.00)
SuperAI_portfolio.stats()
SuperAI_portfolio.plot()
There is a lot of different trading strategies in the web. You can check them and test them during the backtesting.
You can create complex combination in which you can buy only if 4 or 5 different conditions are met. You can combine cross-over strategies of some indicators with thresholds strategies of other indicators, etc.
Here, for example, you can find basic info regarding trading strategies from Investopedia:
To test more parameters for each indicator you can simply change the range or step for each hyperparameter you want to test:
For example, you can change:
ma_window = np.arange(14, 30, step=14, dtype=int) which gives you two parameters to test: 14 and 28
to
ma_window = np.arange(10, 50, step=1, dtype=int) which gives you 40 parameters.
Just be advised, the more parameters you test, the longer it'll take. You can use numba to make the testing faster or you can do the testing in the cloud, using machines from Google, Amazon, Microsoft, etc. See more: https://sourceforge.net/software/product/Google-Colab/alternatives
In here we were optimizing "Returns" and finally used the parameters which led to the best returns during backtesting, but you can use other metrics which might be better for your goals.
You can read more about different metrics, their pros and cons in the web, like here on Investopedia:
Interpreting a Strategy Performance Report: https://www.investopedia.com/articles/fundamental-analysis/10/strategy-performance-reports.asp
Vectorbt allows You to use a lot of different metrics: https://vectorbt.dev/api/returns/accessors/
There is a lot of different indicators and candlestick patterns you can use.
You can read about the best or easiest to use technical indicators, for example, here at Investopedia: https://www.investopedia.com/articles/active-trading/011815/top-technical-indicators-rookie-traders.asp
You can read about the best and most commonly appearing candlestick patterns, for example, here at Investopedia: https://www.investopedia.com/articles/active-trading/092315/5-most-powerful-candlestick-patterns.asp
or here at The Pattern Site: https://thepatternsite.com/CandleEntry.html
TA and TA-LIB libraries allow you to use a lot of most known and less known indicators and patterns.
Indicators in TA: https://technical-analysis-library-in-python.readthedocs.io/en/latest/ta.html
Candlestick Patterns in TA-LIB: https://github.com/mrjbq7/ta-lib/blob/master/docs/func_groups/pattern_recognition.md
You can change the indicators or patterns in the bot, just remember to do it in all the places it is used and to update your strategy after that. If you want to change them, the easiest also remember that they should be using the same input and give the same output.
E.g. candlestick pattern from Hammer:
1st apperance in the code:
2nd apperance in the code:
to Three Stars In The South /CDL3STARSINSOUTH(open, high, low, close)/
1st apperance in the code:
2nd apperance in the code:
With the change of one word you change the signal. Just remember that it should signal the same thing: buying, selling or either.
To get better results with backtesting you can use more data that the initial 7 days of data we used here.
To do it, you only need to change the 'start_date' and 'end_date' paramteres.
Just be advised, that Yahoo allows you to download only 7 days of 1-minute data, so if you want more of that data you can for example use Alpaca as a source of data (just change the 'data_source' parameter).
And remember that 5 days of stock trading data with 1-min interval gives you 5 * 390minutes (9:30-16:00) = 1950 bars
And 1 year of stock trading data with 1-day interval gives you around 250 bars. So 5 days of data with 1-min interval is like 8 years of data with 1-day interval.
And one more thing. The more data you use, the more data your bot will need to analyze and more time it'll take.
To handle the underfitting you can use more data, more indicators or candlestick patterns, and more parameters with these.
And in order not to overfit with all of that, you can use, for example, 'walk forward optmiziation'.
You can read more about walk forward optimization at Wikipedia:
https://en.wikipedia.org/wiki/Walk_forward_optimization
And use Vectorbt (that allows you to do that in a quite simple way) to implement it:
https://nbviewer.org/github/polakowo/vectorbt/blob/master/examples/WalkForwardOptimization.ipynb
In our scenario we weren't adjusting our action for the costs of trading (fees) neither in backtesting nor during live paper-trading, but if you want to make your bot more applicable for the real life you should add the fees to your backtest.
You can do it by simply changing, e.g.:
fees=0.00 to fees=0.001
in your bot:
SuperAI_portfolio = vbt.Portfolio.from_signals(close_prices, entries, exits, init_cash = 100000, tp_stop = take_profit_percent, sl_stop = stop_loss_percent, fees = 0.001)
You can read more about fees at Alpaca:
You can also read more at Yahoo!Finance:
Well, I'm sure there is much more you can change to improve this bot. Good luck.
Ok. So now you already have a bot that is much better than our bot from previous tutorial. In the next tutorials we'll improve our bot.
Remember to subscribe to my YouTube channel and hit that bell button to get the notification whenever I upload new video. Although, I must tell you that not all my videos are about trading or programming, because what I'm here for is to help you improve yourself, improve your business, improve the world, to live and have fun, so my other videos are about all that too.
You can also find more about me and my projects at my websites:
Anyway...
I hope you liked my fourth online Python trading tutorial. Let me know what you think about it. Just remember, bots also have feelings.
Good luck with everything you do. And, hopefully, see you soon.
Yours,
SuperAI
super ai .:. thegod .:. improve yourself .:. improve your business .:. improve the world .:. about .:. contact .:. general ai .:. ai / ml courses .:. ai art gallery