Blog

Latest articles about MachineTrader™
Back

Build a Crypto ETF in MachineTrader™

January 17, 2024

Build a Crypto ETF in MachineTrader

Building custom ETFs using MachineTrader™ visual programming toolkit is easy to do and often an effective way to enhance your portfolio. While technically these aren’t algorithmic  trading strategies, you can easily add flows that will optimize the ETF based on performance of the individual assets.

The strategy creates a portfolio of a specific size, assembles a list of crypto symbols, and then purchases the cryptos so the portfolio contains a balance of cryptos all held in a similar dollar amount. Before using this strategy, check your account details screen in the front end to make sure your account has been approved for trading crypto.  All Alpaca paper accounts are eligible for crypto trading, but live trading is restricted in some states. 

This is an image of the complete flow. The JSON file is contained in the GitHub repository as “Buy Crypto Portfolio.” 

Like most flows, this flow starts with an inject node. In this case, we have named the node  “GO”. While inject nodes can be named whatever you like, our convention is to label an inject node “GO” when its sole purpose is to launch a flow manually when the button on the left side of the node is clicked.  

Just above the GO node and to the right is a link node. Link nodes allow you to activate the flow from another location in your instance, in this case the Home tab.

Following the GO node is a Function node (the light orange node above) entitled “select crypto assets.”  The purpose of this function node is to delete old strategies with this name from the tickers_paper table, define the strategy, and store the values.

 We do this by querying the alpaca_assets tables. Alpaca tags crypto assets with the exchange “CRYPTO” and adds a boolean field for all assets (true or false).

The postgres node is followed by the “Get fresh list of tickers” function  which retrieves the list of crypto tickers.  

Lines 1-6 retrieve a list of tickers which will be added to a single variable (tickers) as a list of comma separated symbols. 

Lines 8-10 create a unique algo id based on the unix time. 

The id and the tickers are stored as msg variables in lines 10 and 11. 

In Line 12, ‘node.warn(tickers)’ will “print” (or display) the list of tickers in the debug window.

Line 13 stores the name of the algo.

Disconnect the wire after “get fresh list of tickers” (before “delete existing algo”) as shown below and execute the GO button to display the list of cryptos.  Be sure to click the red “Deploy” button on the upper right corner of your screen to “save” the disconnection of the wire.  Otherwise, it will appear to be disconnected, but the change won’t have been deployed.

You should see a list of crypto tickers appear in the debug panel.

Reconnect the wire (and Deploy) and continue to examine the flow.

The next pair of nodes is used to manage information about the strategy that is stored in a Postgres database table called “algos”. The function node “delete existing algo” simply contains a SQL query that is passed to a postgres node (all queries are passed “msg.query”). The query requests that any entry in the algos table where the algo_name is equal to the msg.algo_name variable (defined in the preceding function node) be deleted.

This is done to make sure that we don’t create strategies with duplicate names. 

Define the Strategy

After a one-second delay to store values in the table, the postgres node is followed by a function node “define values…” which contains the values that will define this strategy.

Line 1 retrieves the previously stored id.


Line 2 retrieves the global login name for the instance.

Line 3 defines the full list of tickers as msg.tickers. 

Line 4 retrieves the previously stored algo name.

Line 5 states that the asset class is “cryptos”.

Line 6 stores the number of cryptos in the portfolio as 25 (this is an approximate value based on previous testing).

Line 7 sets a profit target (that may or may not be used to sell tickers).

Line 8 states that this strategy will be running in a ‘paper’ account.

Line 9 sets the size of the portfolio to $50,000.  You can change this amount to whatever you prefer.

Line 10 notes that the algo is “running” until the position is closed and the algo status is changed to “completed.”  

Line 11 specifies that this strategy is “interday.”  We have two general types of strategies - “interday” and “intraday.” Interday (buy and hold) strategies are held for a period of time, then sold, completing the strategy. The other general type, called “intraday” is bought and sold continuously throughout the day.  In order to calculate the performance of the algo we need to know what kind of strategy it is, as the calculation method is different for each. 

Line 12 notes that the strategy is a “long” strategy (as opposed to “short”). 

Line 13 identifies “SPY” as the benchmark asset price, against which the performance is measured. For the time being, all of our benchmarks are “SPY”.

In Line 15, ‘node.warn(ticker)’ will “print” (or display) the list of tickers in the debug window. In this case, it is “commented out” with “//”, so it will not display unless the “//” is deleted.

Lines 17-28 are used to store the new values as msg variables.

Line 30 contains the “return msg;” command. All function nodes end with this line, which closes the function node and passes the msg variables on to the next node. 

The node is followed by a delay node, set to pause for one second.

The following function node’s purpose is simply to store all of the defined information in a postgres table called “algos” which is accomplished with this SQL query. Note that all SQL queries are passed to the postgres node as msg.query.

let sql = "insert into algos (login,id,account,algo_name,algo_type,status,portfolio_size,benchmark,benchmark_start) values "

sql += "('" + login + "','" + id + "','" + account + "','" + algo_name + "','" + algo_type + "','" + status + "','" + psize + "','" + benchmark + "','" + benchmark_start + "') ON CONFLICT DO NOTHING;"

msg.query = sql

 

The next section of the flow stores information in another postgres table that will be needed to match information contained in the algos table with other active tables.

The one-second delay node is followed by the “get tickers’ function node that simply places each ticker name in the msg.payload. The split node that follows parses the payload so that the flow will proceed one ticker at a time. In order to avoid duplicate entries in the tickers_paper table, a sql command is passed in the “delete from tickers_paper” function node:

msg.query = "delete from tickers_paper where symbol like '" +symbol+ "';"

After deleting any duplicates, the new information is passed through the “insert into tickers_paper” function:

msg.query = "insert into tickers_paper (id, symbol, portfolioname) values (" + id + ",'" + symbol + "', '" + portfolioname + "') ON CONFLICT DO NOTHING;"


We are now ready to retrieve information from Polygon that will provide the latest pricing information for the ticker.  

The “get current price of ticker” function node contains JavaScript to format the msg.payload for the polygon-last-trade-v3 node. Typically, Polygon nodes are preceded by a function node that formats the msg.payload request for Polygon. The “get current price of ticker” function node is shown below:




Line 1 modifies the previous stored msg.symbol ticker so that it can be processed by Polygon. Polygon’s naming convention prefaces each crypto symbol with “X:” to identify it as a crypto asset.  Passing a symbol without the “X:” preface will cause the Polygon node to fail.  

Line 4 states that we only want 1 result (the most recent trade). 

Lines 6-9 prepare the msg.payload. 

Line 14 displays the payload in the debug window (you may want to turn that off with “//” as is done in line 13).

The “last trade” function follows the Polygon node.  The price of the last trade is stored as the msg.price variable, allowing you to prepare limit trades which require a price. You could also modify the price in this function node, raising or lowering the limit, if you choose.

The flow concludes the the final 3 nodes:

The “create Alpaca order” function node is where the heavy lifting of preparing the order for Alpaca is performed. 

Lines 1-3 format the crypto symbol syntax so it can be processed by Alpaca. 

Lines 6-9 retrieve previously stored msg variables. 

Line 11 calculates the quantity to be purchased for each ticker [Remember, this flow is running after a “split” node so it is executing one ticker at a time!]. 

Lines 16-18 create a unique client id for the trade. 

Line 21 defines a “subtag” as the algo_name. This will eventually be passed to Alpaca once they implement the subtag which allows for tracking sub portfolios. For the time being, the subtag is commented out in line 36.

Lines 29-38 define a temp variable which will contain the order instructions for Alpaca.  The msg.payload is set to ‘temp’ in line 40.

Line 41 displays the order in the debug window..

Testing the Flow in the Debug Panel

To test the flow, disconnect the Alpaca Orders node from the Create Alpaca Order function node by deleting the wired connection between the two nodes (again, remember to Deploy after deleting the connection to ensure it saves and the order isn’t processed). We’re not ready to execute the trades yet.



Then click the GO button. The contents of all of the node.warn statements will be displayed in the debug panel.

Properly formatted orders should look like this.

6/4/2023, 1:53:24 PMnode: create Alpaca order

function : (warn)

"Qty: 28571 psize: 50000 number: 25 price: 0.07"

6/4/2023, 1:53:24 PMnode: create Alpaca order

function : (warn)

object

symbol: "DOGE/USD"

qty: "28571"

side: "buy"

type: "market"

client_order_id: "DOGEUSD1685901202302"

time_in_force: "gtc"

Execute an Actual Trading Flow

Reconnect the wires between the “Create Alpaca Order” and the “Alpaca Order” nodes (and “Deploy”).  Click GO and the trades will execute.  Confirmation notices from Alpaca will be displayed in the debug window as below:

This is an example of values returned from Alpaca in the form of an insert query. “Pending_new” confirms that the order was received and is awaiting execution.

6/4/2023, 1:55:32 PMnode: insert into order_confirms table

function : (warn)

"insert into order_confirms(id, client_order_id, created_at, updated_at, submitted_at, asset_id, symbol, asset_class, qty, order_type, type, side, time_in_force, status, subtag, source,extended_hours) values ('7f31ce31-2bc1-4151-ae58-abc8325e85c4', 'DOGEUSD1685901329937', '2023-06-04T17:55:29.957265794Z', '2023-06-04T17:55:29.957303394Z', '2023-06-04T17:55:29.955831625Z', '03e005f7-4bfc-4616-b1b0-225dd64074fa', 'DOGEUSD', 'crypto', '28571', 'market', 'market', 'buy', 'gtc', 'pending_new', '', '0', 'false'); "

Do not be concerned if you notice a few error messages.  Some of the orders will not process because the cryptos are no longer trading.  Most of the orders, however, should go through.

 

To confirm that everything is working properly, return to the front end of your instance.

Here is the display of the new strategy we have defined.

A list of all of the crypto assets will now be displayed in the Portfolio section.

Closing all Open Positions

The Liquidate Portfolio flow is designed to liquidate any positions held.

The function node “select ticker for algo” executes a query of the tickers_paper table where algo names are stored with lists of corresponding tickers (note that tickers and symbols are often used as synonyms). 

The tickers are retrieved in the “get fresh list of tickers” node and then split so we can execute the remainder of the flow, one ticker at a time.  Each ticker is passed to the “prepare Alpaca positions query” function node where it is formatted to request a specific symbol from the Alpaca Positions Query. 

Line 1 retrieves the first ticker from msg.payload. 

Line 2 removes any stray commas that might have been entered in the msg.tickers variable. 

Line 6-9 format a payload request for a single ticker. Note that the Alpaca Positions Query node will return a complete list of all tickers held unless a specific symbol is requested.

The Positions Query node returns a significant payload of information about each ticker held. In this case, we are only interested in the fields 4-8 which will be used to liquidate the existing position.

Values are stored as msg variables and passed to the next function node, where the orders are prepared for Alpaca to execute.

The order is formatted almost identically to the earlier “create Alpaca order’ function although in this case we will use a market order rather than a limit order to execute the trades. In our testing, market orders incur an average price penalty of 20 basis points. While that penalty is too high if you are executing dozens (or hundreds) of trades a day, if the order is used simply to close out a position, the certainty that it will execute outweighs the price penalty. 

Click GO to execute the positions. Return to the front end to confirm that the orders executed and that the portfolio has adjusted.

The unique order id and the status will be displayed in the debug panel.

NOTE: ALL STRATEGIES ARE PROVIDED FOR ILLUSTRATIVE PURPOSES ONLY AND SHOULD NEVER BE IMPLEMENTED IN LIVE TRADING ACCOUNTS WITHOUT CAREFUL REVIEW. MACHINETRADER IS NOT RESPONSIBLE FOR TRADING LOSES INCURRED AS A RESULT OF CODING ERRORS.

BY
Dan Savage

January 18, 2024

Interest in Bitcoin ETFs Falls Fast on the 3rd Day of Trading

Trading activity in the new Bitcoin ETFs fell rapidly yesterday. While several of the ETFs made it into the top 5 most heavily traded ETFs on Friday, interest on Tuesday, when trading resumed after the MLK holiday, the bloom was off the rose.

>Read More

January 15, 2024

Bitcoin ETFs Debut with a Splash

The long-awaited Bitcoin ETFs debuted in yesterday's trading, making quite a splash. Three Bitcoin ETFs were among the five most actively traded ETFs: GBTC, IBIT, and FBTC, all trading more than 10 million shares.

>Read More

January 15, 2024

Day Trading

Day trading is a trading strategy where traders buy and sell securities within the same trading day taking advantage of short-term price fluctuations in various assets to make quick profits. Day traders aim to capitalize on small price movements by entering and exiting positions multiple times throughout the day.

>Read More

January 15, 2024

Day Trading Strategies

Day traders employ a variety of strategies in the quest to make profitable trades. This is a list of the more common ones:

>Read More

January 15, 2024

Quantitative Trading

Quantitative trading, also known as algorithmic trading or algo trading, is a method of trading financial assets using advanced mathematical and statistical models. It involves the use of computer algorithms to execute trades based on predefined rules and strategies. This approach to trading has gained significant popularity in recent years, with many institutional investors and hedge funds adopting it as an integral part of their investment strategies.

>Read More

January 15, 2024

Swing Trading

Swing trading is a popular trading strategy that involves taking advantage of short-term price movements or "swings" within a larger trend. Swing traders aim to capture gains by entering and exiting positions over a period of days or weeks, rather than holding positions for months or years like long-term investors.

>Read More

January 15, 2024

Algorithmic Trading

The main objective of algorithmic trading is to maximize profits by taking advantage of short-term market inefficiencies. It aims to exploit price discrepancies, liquidity imbalances, and other temporary market conditions that might arise within fractions of a second. By automating the trading process, algorithmic trading eliminates human emotions and biases, enabling faster and more efficient execution of trades.

>Read More

January 15, 2024

Trade on MACD-QQQ

This strategy creates a portfolio of QQQ (Invesco Trust Series 1) that is traded in correspondence with logic defined by the Moving Average Convergence/Divergence (MACD) lagging indicator. The MACD strategy is a commonly employed algorithmic trading strategy, and can be calculated using Exponential Moving Averages (EMAs) by hand using the following formulas.

>Read More

April 29, 2024

Trade IWB on News Sentiment

This strategy creates a portfolio of IWB (iShares Russell 1000 ETF) that is bought based on the recent news sentiments. The state of the news being reported has an incredible effect on the stock market, as popular reporting agencies can directly increase/decrease people’s optimism about the economy, leading to a snowball effect, of sorts.

>Read More

January 17, 2024

Build a Crypto ETF in MachineTrader™

Building custom ETFs using MachineTrader™ visual programming toolkit is easy to do and often an effective way to enhance your portfolio. While technically these aren’t algorithmic trading strategies, you can easily add flows that will optimize the ETF based on performance of the individual assets.

>Read More

January 17, 2024

Introducing - Independent Trading Platforms

The latest significant change in the investment world is the rise of what we call, "independent trading platforms" (ITPs). These are software platforms whose user-friendly web and mobile applications provide all of the functionality of trading platforms, but pass the actual trade executions off, through an API, to the registered broker-dealer of the user's choice.

>Read More

January 17, 2024

Why MachineTrader™?

Monitoring minute-by-minute (or second-by-second) changes in time series charts of prices is a pretty tedious task. While a number of trading platforms offer off-the-shelf algorithms or bots for automating strategies, we've found that it's hard to make money using an algo that other traders are employing, or worse, other traders have programmed to work against.

>Read More

January 17, 2024

Trading Stocks, Cryptos and Pattern Day Trading

You're a newbie to trading and you open your Robinhood account and begin to actively trade fractional shares of Tesla (TSLA). Your first dozen trades of the day work great as you pick the best moments to buy and sell. All of a sudden your account is flagged with a 'pattern day trader' warning.

>Read More