Skip to content

Commit

Permalink
Add helper scripts for quickstart, update docs accordingly
Browse files Browse the repository at this point in the history
  • Loading branch information
flancast90 committed Feb 14, 2023
1 parent 849be29 commit 0400298
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 58 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
__pycache__
config.py
__pycache__
43 changes: 41 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@
# HFT-EXT
> An extensible framework for high-frequency trading built on top of [Alpaca](https://alpaca.markets/) and Yahoo Finance.
## Table of Contents
- [HFT-EXT](#hft-ext)
- [Table of Contents](#table-of-contents)
- [Disclaimer](#disclaimer)
- [Why should I use HFT-EXT?](#why-should-i-use-hft-ext)
- [I'm sold! How do I get started?](#im-sold-how-do-i-get-started)
- [I have a working strategy! How do I deploy it to live trading?](#i-have-a-working-strategy-how-do-i-deploy-it-to-live-trading)
- [How do I add my own strategies?](#how-do-i-add-my-own-strategies)
- [What about if I want to change the amount of shares I buy for each pricepoint?](#what-about-if-i-want-to-change-the-amount-of-shares-i-buy-for-each-pricepoint)
- [This is great, but I wish I could customize which tickers I want to trade.](#this-is-great-but-i-wish-i-could-customize-which-tickers-i-want-to-trade)
- [I want to get to modifying the framework, but I don't know where to start.](#i-want-to-get-to-modifying-the-framework-but-i-dont-know-where-to-start)
- [I want to contribute!](#i-want-to-contribute)


## Disclaimer
_It goes without saying that past performance is not indicative of future results. This framework is not intended to be used for live trading. If you do use it for live trading, you do so at your own risk. The authors of this framework are not responsible for any losses incurred by using this framework. Please use this framework responsibly._

Expand All @@ -33,7 +47,15 @@ Then, you need to install the dependencies. You can do this by running the follo
cd hft-ext
pip install -r requirements.txt
```
Finally, you need to add your API keys to the `config.example.py` file. Simply fill the `ALPACA_PUBLIC_KEY` and `ALPACA_SECRET_KEY` variables with your API keys. Then, rename the file to `config.py`. You can now run the framework by running the following command in your terminal:
Finally, you need to add your API keys to the `config.py` file. We have a built-in script that will help you do this. You can run this script by running the following command in your terminal:
```bash
cd helpers
python auth.py
```
The script should look like this:
![auth-example](images/auth-example.png)

From there, make sure you are back in the root directory ``cd ..`` and run the following command in your terminal:
```bash
python main.py
```
Expand Down Expand Up @@ -68,8 +90,25 @@ strategy = Strategy(ArimaStrategy())
The default strategy used is the ARIMA strategy. You can find the code for this strategy in the `scripts/strategies.py` file, within the `ArimaStrategy` class.


## What about if I want to change the amount of shares I buy for each pricepoint?
By default, the model will buy a total of $200 worth of shares for each pricepoint. We recognize that this may be a bit too much for some people, so we have made it easy to change this. You can run the following command in your terminal to change the amount of shares you buy for each pricepoint:
```bash
cd helpers
python amount.py
```
The script should look like this:
![amount-example](images/amount-example.png)
Which is also the default setting.


## This is great, but I wish I could customize which tickers I want to trade.
You can customize which tickers you want to trade by adding them to the `config.py` file. Simply add the tickers you want to trade to the `TRADE_TICKERS` variable. For example, if you want to trade Apple, Microsoft, and Tesla, you would add `TRADE_TICKERS = ["AAPL", "MSFT", "TSLA"]` to the `config.py` file. However, it is recommended that you use the default tickers, as they are the ones that have been tested and are known to work well with the framework.
You can customize which tickers you want to trade by adding them to the `config.py` file. We have a built-in script that will help you do this. You can run this script by running the following command in your terminal:
```bash
cd helpers
python tickers.py
```
The script should look like this:
![tickers-example](images/tickers-example.png)

As an aside, there are no limits to the number of tickers you can trade. However, the more tickers you trade, the more you risk running into API rate limits. If you do run into API rate limits, you can simply wait a few minutes and try again. If you want to avoid this, you can simply trade fewer tickers.

Expand Down
54 changes: 0 additions & 54 deletions config.example.py

This file was deleted.

37 changes: 37 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# These are our API keys and other configuration settings
# for the Alpaca API and the trading algorithm.
# ALPACA_PUBLIC_KEY is the API key ID for your account.
# ALPACA_SECRET_KEY is the "passphrase" for your API key.
# PAPER is a boolean value that determines whether we are
# using the paper trading API or the live trading API.
# You can configure these values by running the helpers/auth.py script.
ALPACA_PUBLIC_KEY = "<my api id key>"
ALPACA_SECRET_KEY = "<my api secret key>"
PAPER = True

# ALPACA_TIMEOUT is the number of seconds we will wait for
# to avoid rate limiting. This same value is used for both
# Yahoo Finance and Alpaca. It defaults to 3 seconds.
ALPACA_TIMEOUT = 3.0

# SHARES_BY_PRICE is a dictionary that maps the price of a
# share to the number of shares we want to buy at that price.
# For example, we want to buy 200 shares at $1, 100 shares
# at $2, 40 shares at $5, 20 shares at $10, 10 shares at $20, ...
# You can configure this dictionary by running the helpers/amount.py script.
SHARES_BY_PRICE = {1: 200, 2: 100, 5: 40, 10: 20, 50: 4, 100: 2}

# TRADE_TICKERS is a list of the tickers we want to trade.
# We will use the first 100 tickers in the S&P 500 by default.
# You can change this list to any other tickers you want.
# You can configure this list by running the helpers/tickers.py script.
TRADE_TICKERS = [ "AAPL", "MSFT", "AMZN", "GOOG", "FB", "JPM", "JNJ", "V", "PG", "UNH", "MA", "HD", "VZ", "DIS", "BAC", "INTC", "T", "PFE", "CMCSA", "WFC", "KO", "PEP", "NFLX", "NVDA", "ADBE", "CRM", "TMO", "CSCO", "ABT", "NKE", "MRK", "MDT", "ACN", "COST", "AVGO", "TXN", "QCOM", "UNP", "NEE", "PYPL", "LIN", "PM", "CVX", "MCD", "ORCL", "UPS", "IBM", "LOW", "MMM", "AMGN", "GS", "BA", "CAT", "XOM", "WMT", "DHR", "AMT", "AXP", "HON", "CVS", "BKNG", "CHTR", "SBUX", "GILD", "MDLZ", "BLK", "INTU", "TGT", "ZTS", "WBA", "MU", "GE", "MCK", "GPN", "FIS", "USB", "DUK", "DOW", "PLD", "RTX", "ANTM", "DE", "ISRG", "SYK", "LMT", "CI", "MS", "TJX", "BK", "C", "PNC", "SPGI", "ADP", "CL", "SO", "CME", "COP", "MDXG", "CNC", "CARR", "CRL", "CPB", "COF", "CAH", "KMX", "KHC", "K", "KEY", "KMB", "KIM", "KMI", "KLAC", "KSS", "KDP", "KR", "LB", "LHX", "LH", "LRCX", "LW", "LVS", "LEG", "LDOS", "LEN", "LLY", "LNC", "LIN", "LYB", "LKQ", "LMT", "L", "LOW", "LUMN", "LYV", "MTB", "MRO", "MPC", "MKTX", "MAR", "MMC", "MLM", "MAS", "MA", "MKC", "MXIM", "MCD", "MCK", "MDT", "MRK", "MET", "MTD", "MGM", "MCHP", "MU", "MSFT", "MAA", "MHK", "TAP", "MDLZ", "MNST", "MCO", "MS", "MOS", "MSI", "MSCI", "MYL", "NDAQ", "NOV", "NTAP", "NFLX", "NWL", "NEM", "NWSA", "NWS", "NEE", "NLSN", "NKE", "NI", "NSC", "NTRS", "NOC", "NLOK", "NCLH", "NRG", "NUE", "NVDA", "NVR", "ORLY", "OXY", "ODFL", "OMC", "OKE", "ORCL", "PCAR", "PKG", "PH", "PAYX", "PAYC", "PYPL", "PNR", "PBCT", "PEP", "PKI", "PRGO", "PFE", "PM", "PSX", "PNW", "PXD", "PNC", "POOL", "PPG", "PPL", "PFG", "PG", "PGR", "PLD", "PRU", "PTC", "PEG", "PSA", "PHM", "PVH", "QRVO", "PWR", "QCOM", "DGX", "RL", "RJF", "RTX", "O", "REG", "REGN", "RF", "RSG", "RMD", "RHI", "ROK", "ROL", "ROP", "ROST", "RCL", "SPGI", "CRM", "SBAC", "SLB", "STX", "SEE", "SRE", "NOW", "SHW", "SPG", "SWKS", "SLG", "SNA", "SO", "LUV", "SWK", "SBUX", "STT", "STE", "SYK", "SIVB", "SYF", "SNPS", "SYY", "TMUS", "TROW", "TTWO", "TPR", "TGT", "TEL", "TDY", "TFX", "TER", "TSLA", "TXN", "TXT", "TMO", "TJX", "TSCO", "TT", "TDG", "TRV", "TRMB", "TFC", "TWTR", "TYL", "TSN", "UDR", "ULTA", "USB", "UAA", "UA", "UNP", "UAL", "UNH", "UPS", "URI", "UHS", "UNM", "VLO", "VTR", "VRSN", "VRSK", "VZ", "VRTX", "VFC", "VIAC", "VTRS", "V", "VNO", "VMC", "WRB", "WAB", "WMT", "WBA", "DIS", "WM", "WAT", "WEC", "WFC", "WELL", "WST", "WDC", "WU", "WRK", "WY", "WHR", "WMB", "WLTW", "WYNN", "XEL", "XRX", "XYL", "YUM", "ZBRA", "ZBH", "ZION", "ZTS"]

# CHOOSE_AMOUNT is a function that takes a price and returns
# the number of shares we want to buy at that price. It is not
# configurable, but you can change it if you want.
def CHOOSE_AMOUNT(value):
for key in SHARES_BY_PRICE:
if value <= key:
return SHARES_BY_PRICE[key]
return 1
43 changes: 43 additions & 0 deletions helpers/amount.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
class COLORS:
BLUE = "\033[94m"
END = "\033[0m"
RED = "\033[91m"
YELLOW = "\033[93m"
GREEN = "\033[92m"


def main():
shares_by_price = {}

# Ask the user to enter their preferred stock prices and corresponding shares to buy
while True:
try:
price = int(
# print blue text
input(
f"""{COLORS.BLUE}Enter a stock price for a new rule (or -1 to stop).
For example, entering 1000 will allow you to set the amount of shares to
buy when the stock price is $1000 or less:{COLORS.END} """
)
)
if price == -1:
break
shares = int(input(f"{COLORS.YELLOW}Enter the number of shares to buy for this rule:{COLORS.END} "))
shares_by_price[price] = shares
except ValueError:
print("Invalid input, please try again.")

with open('../config.py', 'r') as f:
lines = f.readlines()
with open("../config.py", "w") as f:
for line in lines:
if line.startswith("SHARES_BY_PRICE"):
f.write(f"SHARES_BY_PRICE = {shares_by_price}\n")
else:
f.write(line)

print(f"{COLORS.GREEN}Successfully updated config.py!{COLORS.END}")


if __name__ == "__main__":
main()
36 changes: 36 additions & 0 deletions helpers/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class COLORS:
BLUE = "\033[94m"
END = "\033[0m"
RED = "\033[91m"
YELLOW = "\033[93m"
GREEN = "\033[92m"


def main():
try:
public = str(input(f"{COLORS.BLUE}Enter your Alpaca API Key ID:{COLORS.END} "))
private = str(input(f"{COLORS.BLUE}Enter your Alpaca API Secret Key:{COLORS.END} "))
paper = str(input(f"{COLORS.BLUE}Are you using a paper account? (y/n):{COLORS.END} "))
except ValueError:
print("Invalid input, please try again.")

with open("../config.py", "r") as f:
lines = f.readlines()
# Generate the dictionary and save it to the config file
with open("../config.py", "w") as f:
for line in lines:
if line.startswith("ALPACA_PUBLIC_KEY"):
f.write(f"ALPACA_PUBLIC_KEY = '{str(public)}'\n")
elif line.startswith("ALPACA_SECRET_KEY"):
f.write(f"ALPACA_SECRET_KEY = '{str(private)}'\n")
elif line.startswith("PAPER"):
boolean = paper.lower() == "y" or paper.lower() == "yes"
f.write(f"PAPER = {boolean}\n")
else:
f.write(line)

print(f"{COLORS.GREEN}Successfully updated config.py!{COLORS.END}")


if __name__ == "__main__":
main()
33 changes: 33 additions & 0 deletions helpers/tickers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class COLORS:
BLUE = "\033[94m"
END = "\033[0m"
RED = "\033[91m"
YELLOW = "\033[93m"
GREEN = "\033[92m"


def main():
tickers = []

while True:
try:
ticker = str(input(f"{COLORS.BLUE}Enter a ticker you would like to trade (or -1 to stop):{COLORS.END} "))
if ticker == '-1': break
tickers.append(ticker)
except ValueError:
print("Invalid input, please try again.")

with open("../config.py", "r") as f:
lines = f.readlines()
with open("../config.py", "w") as f:
for line in lines:
if line.startswith("TRADE_TICKERS"):
f.write(f"TRADE_TICKERS = {tickers}\n")
else:
f.write(line)

print(f"{COLORS.GREEN}Successfully updated config.py!{COLORS.END}")


if __name__ == "__main__":
main()
Binary file added images/amount-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/auth-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/tickers-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0400298

Please sign in to comment.