Simple Express server that helps automate Buy and Sell stock orders through TD Ameritrade API.
This programs exposes API endpoints where you can send a POST request to Buy or Sell stocks for TD Ameritrade. It does not decide what/when to Buy or Sell. You need to find a Signal Provider, or write your own program to send a POST request to this server to execute the trade. For example, you can consider running this program on a cloud server and send the trading signal through webhooks.
Example usage:
- Run this server in AWS (set up proper firewall filtering)
- Formulate strategies in TradingView
- Use TradingView webhook to send POST request to your server
- Buy and Sell Stocks automatically
- Log all trades to a Logbook to be viewed easily
- Automatically close all open trades at 15:50 New York Time each day
- Send trade summary to a Telegram group of your choice each day at 15:50
- Only market buy and market sell of Stocks are supported and tested. Limit orders are not added in this version.
- Only equity instruments are tested. Options/futures trades may not function properly. Use at your own risk.
- Only orders with 1 leg will be supported.
- For short trading days, automatic closing of trades at 15:50 hr will not work.
Note: To prevent yourself from being flagged as a Pattern Day Trader, make sure you have at least $25k in your account, or you are using a cash account.
- Clone this project
- Run
npm install
on root folder of project - Create a file
.env
in root folder of project, using the template below. This will contain all your credentials. - Run
npm run dev
during development. Runnpm run start
for production. To stop production, runnpm run stop
.
.env
Template:
PORT=8000
AUTH=enter_some_string_here_of_your_choice
REFRESH_TOKEN=your_refresh_token_here
CONSUMER_KEY=your_consumer_key_without_@AMER.OAUTHAP
ACCOUNT_ID=nine_digits_tdameritrade_account_id
TELEGRAM_TOKEN=your_telegram_token_to_send_the_bot_msg_from
TELEGRAM_CHAT_ID=your_telegram_chat_id_to_send_bot_msg_to
For how to get your Refresh Token, Consumer Key and Account Id, please look at the official docs from TD Ameritrade. Note: You do not need to input Access Token, as it will be automatically fetched with your Refresh Token.
The following cron-job will run at 15:50 New York Time from Monday-Friday:
- Close all open Long/Short orders (that were executed by this program only).
- Send today's summary to Telegram.
- Send an error message to Telegram if encountered Error today.
- /market_buy
- /market_sell
- /market_order
- /market_close_all
- /add_unavailable_date
- /logbook
- /config
- /stop
- /start
In general, for all POST
endpoints, you will need to send a field auth
that corresponds to the AUTH in .env
file. This will then authenticate you and allow the endpoints to pass. GET
endpoints do not require this auth
fields as these endpoints are generally safe.
In Buy and Sell order, there is this concept of strategy
. In short, strategy
is a name you give to identify the order, so that different strategies can purchase the same ticker. For example, if you send a Buy order with the strategy name strategy1
to buy 10 SPY, subsequently if you send another Buy order with strategy name strategy1
again to buy 10 SPY, the buy order will do nothing. But if you send the Buy order with another strategy name, such as strategy2
, then the Buy order will go through and allows you to manage 2 different Buy positions. When you want to link a Sell order to a Buy order, or vice versa, use the same strategy name, otherwise they will be treated as 2 different positions.
- Send a POST request to put in a Market Buy Order for a particular ticker.
- If there is already an opened Short order for this strategy that is not closed yet, we will proceed to close that instead.
- If there is already an opened Long order for this strategy, then do nothing.
curl -X POST -H "Content-Type: application/json" -d '{"auth": "MY_SOME_AUTH", "symbol": "SPY", "quantity": 1, "strategy": "My Strategy Name"}' http://localhost:8000/market_buy
Signature | Explanation | |
Request Body |
{
auth: string,
symbol: string,
quantity: number,
strategy: string,
} |
|
Response Body | Status: 200 | 422 | 503 |
|
- Send a POST request to put in a Market Sell Order for a particular ticker.
- If there is already an opened Long order for this strategy that is not closed yet, we will proceed to close that instead.
- If there is already an opened Short order for this strategy, then do nothing.
curl -X POST -H "Content-Type: application/json" -d '{"auth": "MY_SOME_AUTH", "symbol": "SPY", "quantity": 1, "strategy": "My Strategy Name"}' http://localhost:8000/market_sell
Signature | Explanation | |
Request Body |
{
auth: string,
symbol: string,
quantity: number,
strategy: string,
} |
|
Response Body | Status: 200 | 422 | 503 |
|
- Send a POST request to put in a Market Buy or Market Sell Order for a particular ticker.
- This is the same as calling /market_buy or /market_sell, except we instruct the buy or sell action through the body request.
- If we send in a Market Buy and there is already an opened Short order for this strategy that is not closed yet, we will proceed to close that instead.
- If we send in a Market Buy and there is already an opened Long order for this strategy that is not closed yet, do nothing.
- If we send in a Market Sell and there is already an opened Long order for this strategy that is not closed yet, we will proceed to close that instead.
- If we send in a Market Sell and there is already an opened Short order for this strategy that is not closed yet, do nothing.
curl -X POST -H "Content-Type: application/json" -d '{"auth": "MY_SOME_AUTH", "symbol": "SPY", "quantity": 1, "strategy": "My Strategy Name", "action": "buy"}' http://localhost:8000/market_order
Signature | Explanation | |
Request Body |
{
auth: string,
symbol: string,
quantity: number,
strategy: string,
action: "buy" | "sell"
} |
|
Response Body | Status: 200 | 422 | 503 |
|
- Send a POST request to close all existing open orders, if any, for all strategies.
- If there is no open orders, do nothing.
curl -X POST -H "Content-Type: application/json" -d '{"auth": "MY_SOME_AUTH"}' http://localhost:8000/market_close_all
Signature | Explanation | |
Request Body |
{
auth: string,
} |
|
Response Body | Status: 200 | 503 |
|
- Send a POST request to add an unavailable date to trade, so the app will not trade on that particular date.
- The format of the unavailable_date must be YYYY-MM-YY, in New York time. e.g. "2022-09-03".
curl -X POST -H "Content-Type: application/json" -d '{"auth": "MY_SOME_AUTH", "unavailable_date": "2022-09-03" }' http://localhost:8000/add_unavailable_date
Signature | Explanation | |
Request Body |
{
auth: string,
unavailable_date: string
} |
|
Response Body | Status: 200 | 422 | 503 |
|
- Get the logbook information.
- If date query is specified, retrive information on that particular date.
- If week query is specified, retrieve information on that particular week.
- Otherwise, retrieve all information to date.
- Priority: date > week > all
http://localhost:8000/logbook?type=orders
http://localhost:8000/logbook?type=orders&date=2022-09-19
http://localhost:8000/logbook?type=summary&week=2022-09-w3
Signature | Explanation | |
Request Body |
{
type: 'error' | 'summary' | 'orders'
date?: string,
week?: string,
} |
|
Response Body | Status: 200 | 503 |
|
- View the Config object in disk.
http://localhost:8000/config
- A kill switch to quickly stop all trading. The bot will not executed anymore trades after this API is made.
http://localhost:8000/stop
- Resume the kill switch done in /stop. The bot will continue to execute trades.
http://localhost:8000/start
We use the following open source library to make this app possible:
- Sainglend/tda-api-client
- axios/axios
- iamkun/dayjs
- motdola/dotenv
- expressjs/express
- node-cron/node-cron
- Unitech/pm2
ISC License
Copyright <YEAR> <OWNER>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
I do not provide personal investment advice and I am not a qualified licensed investment/financial advisor. The use of this software, as well as any interactions with me or comments made by me, whether in private or public, should not constitute financial advice or trading advice. Automated trading programs carry a particularly high risk due to their ungoverned nature. Any losses or gains made with one or more of these programs is your own responsibility. We takes no responsibility for any losses incurred or any malfunctions of the software on your account. Money lost by this program will not be refunded, as we are not liable for the transactions made in your accounts. As you are required to store your credentials for this program to execute trades, you are liable to the security of such credentials and will store these credentials in a safe and secure environment. Any lost of credentials due to the usage/attempt usage of this software will be your sole responsibility and we take no responsibility.