The Bollinger strategy trades a single stock during the market trading hours, using intraday stock prices. Each day it starts trading at the market open with no position and a clean slate (reset to its base state), and it stops trading at the market close. It liquidates all its positions just before the market close. Its state is reset overnight to its base state.
You can read more about the theory of the Bollinger strategy in this document.
To implement the Bollinger strategy in MachineTrader, you
need to install the tab named Bollinger Strategy in your
MachineTrader instance.
You can click this link,
to download the file named Bollinger_Strategy.json from the
MachineTrader Community share drive.
This file contains the JavaScript code for the tab named
Bollinger Strategy. You can then import this
JavaScript file into your MachineTrader instance, and it will
create the tab named Bollinger Strategy.
The tab named Bollinger Strategy executes the Bollinger strategy in real time.
Let’s look at the different flows in the tab named Bollinger Strategy.
At the top of the tab, there are flows for downloading the
documentation. You can click on the gray inject nodes to download the
documentation. The second flow downloads the current file that you’re
reading now.
The flows below create the flow variables in the tab Bollinger
Strategy.
Flow variables are variables that are shared between the different nodes
in the same tab. Once the variables are created, they can be used in
other function nodes in the same tab.
You need to run (click) these flows once before the other flows are run.
You don’t need to run these flows every day.
The function called Create flow variables creates the flow variables, such as the stock symbol to trade, the threshold level for the z-score, the position limit (the maximum number of shares the strategy can own at any time), etc.
The Bollinger strategy maintains two PostgreSQL tables, one
for the submitted trade orders and one for the executed (filled)
orders.
The functions called Create table tableSubmits** and Create
table tableFills** create empty PostgreSQL tables (if they don’t
already exist), for storing the submitted orders and for the executed
(filled) orders.
The table called tableSubmits is filled with the orders
submitted to the broker API, and the table called tableFills is
filled with the orders that were confirmed by the broker.
These two tables are erased overnight, so they start empty at the
beginning of each trading day.
The flow below initializes the flow variables just before the market open. The flow runs automatically - you don’t need to click on it.
The flow initializes the flow variables such as the open position
queue, etc., each day just before the market open.
The function node called Initialize flow variables resets the
flow variables to their initial values.
The flow below initializes the prices just after the market open. This flow runs automatically - you don’t need to click on it.
The flow initializes the flow variables such as the previous valid price, the EMA price, the price variance, etc.
The flow below updates the technical indicators with live (recent) prices. The flow runs automatically - you don’t need to click on it.
The first node in this flow is an inject node that runs every \(10\) seconds. That’s the frequency at which
the strategy is run (updated). It can be changed by the user as
needed.
The inject node activates the whole flow, which updates the technical
indicators with the live (current) prices.
The first function in this flow is called Get stock
price.
It extracts the live (current) price of the given (target) stock from
the global array variable containing the last prices of many stocks.
This array is updated every second in the tab called Alpaca
Prices.
The function called Calculate EMA price and volatility
obtains the stock price from the function Get stock price
through a connector, and it calculates (updates) the EMA moving average
price and volatility.
It also scrubs the prices from bad data using the dollar stock return
(equal to the new price minus previous price). If the stock return is
above the threshold, then the new price is ignored, and the previous
valid price is used.
The function called Update tech indicators calculates the
z-scores, using the the average prices and volatilities from the
function Calculate EMA price and volatility.
The flow below runs the Bollinger strategy. The flow runs automatically - you don’t need to click on it.
The first function in this flow called Calculate PnL
calculates the unrealized profits and losses (PnLs) of the open
positions, and also the PnL drawdown from its maximum.
The Bollinger strategy maintains a queue of the strategy’s open
positions throughout the day.
The function Calculate PnL matches the open positions in the
queue with the current stock price, and calculates the unrealized
PnL.
The function called Bollinger strategy executes the
Bollinger strategy, using the z-scores from the function called
Update tech indicators in the flow above it.
The function Bollinger strategy compares the z-scores with the
threshold level \(\theta\), it then
calculates the number of shares to buy or sell, and passes it into the
function called Submit orders.
The function called Submit orders creates a string with the
trade order, and passes it into the yellow Alpaca API node. It also
writes the submitted trade order into the PostgreSQL table called
tableSubmits.
The flow below liquidates all of the strategy’s stock positions at the end of the day. The flow runs automatically - you don’t need to click on it.
The Bollinger strategy maintains a queue of the strategy’s
open positions throughout the day.
The function called Liquidate positions calculates the total
open positions in the queue, and it submits a trade order to liquidate
them, one minute before the market close. The function can also
liquidate the total open positions reported by Alpaca.
The function called Liquidate positions creates a string
with the trade order, and passes it into the yellow Alpaca API node. It
also writes the submitted trade order into the PostgreSQL table called
tableSubmits.
Pressing the gray inject node called Liquidate now liquidates
all of the strategy’s stock positions at any time during the market
trading hours.
The flow below obtains trade confirmations from Alpaca and inserts them into the fill trades table. The flow runs automatically - you don’t need to click on it.
The function called Confirm trades parses the trade
confirmations from Alpaca and inserts them into the table
tableFills.
It writes the time stamp, the stock symbol, the trade type (buy or
sell), the number of shares filled, the fill price, etc.
This allows the user to track the executed trades and troubleshoot any
issues.
The flows below execute trades manually.
The function called Buy 1 share creates a string with the
trade order to buy one share of the stock, and passes it into the yellow
Alpaca API node. It also writes the submitted trade order into the
PostgreSQL table called tableSubmits.
Similarly the function called Sell 1 share.
These functions are activated by pressing the grey inject nodes to their
left.
The flow below erases the trade tables overnight. The flow runs automatically - you don’t need to click on it.
The Bollinger strategy maintains two PostgreSQL tables, one
for the submitted trade orders and one for the executed (filled)
orders.
The function called Get trade tables returns a vector with the
table names, which is then split by the split node.
The function called Erase or Delete trade tables erases
(deletes) the table contents, so they start empty at the beginning of
the next trading day.
The flows below create web links for downloading the trade tables to CSV files.
The two flows below create web links for downloading the trade tables
to CSV files. You don’t need to click on them.
To download the CSV files to their computer, the user needs to run this
shell script.