{ "cells": [ { "cell_type": "markdown", "id": "c9dc167c", "metadata": {}, "source": [ "# How to create a trading bot in Python (2) - for beginners, using RSI, TA-lib, Alpaca, Anaconda." ] }, { "cell_type": "markdown", "id": "8ef06019", "metadata": {}, "source": [ "## The trading bot - code only version" ] }, { "cell_type": "markdown", "id": "68dea90f", "metadata": {}, "source": [ "If you want, you can find the previous tutorial about starting with Anaconda, Alpaca, Jupyter Notebook, and creating a simple trading bot in 10 lines of code at:\n", "\n", "https://superai.pl/the_simple_trading_bot.html" ] }, { "cell_type": "markdown", "id": "588474f1", "metadata": {}, "source": [ "## Install and import dependencies (all the necessary libraries, packages, modules)" ] }, { "cell_type": "code", "execution_count": 1, "id": "8ec757cf", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: alpaca-trade-api in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (1.4.1)\n", "Requirement already satisfied: pandas>=0.18.1 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (1.3.4)\n", "Requirement already satisfied: aiohttp==3.7.4 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (3.7.4)\n", "Requirement already satisfied: websockets<10,>=8.0 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (9.1)\n", "Requirement already satisfied: msgpack==1.0.2 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (1.0.2)\n", "Requirement already satisfied: PyYAML==5.4.1 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (5.4.1)\n", "Requirement already satisfied: numpy>=1.11.1 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (1.21.4)\n", "Requirement already satisfied: requests<3,>2 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (2.26.0)\n", "Requirement already satisfied: urllib3<2,>1.24 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (1.26.7)\n", "Requirement already satisfied: websocket-client<2,>=0.56.0 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from alpaca-trade-api) (1.2.1)\n", "Requirement already satisfied: attrs>=17.3.0 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from aiohttp==3.7.4->alpaca-trade-api) (21.2.0)\n", "Requirement already satisfied: yarl<2.0,>=1.0 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from aiohttp==3.7.4->alpaca-trade-api) (1.7.2)\n", "Requirement already satisfied: chardet<4.0,>=2.0 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from aiohttp==3.7.4->alpaca-trade-api) (3.0.4)\n", "Requirement already satisfied: typing-extensions>=3.6.5 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from aiohttp==3.7.4->alpaca-trade-api) (3.10.0.2)\n", "Requirement already satisfied: multidict<7.0,>=4.5 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from aiohttp==3.7.4->alpaca-trade-api) (5.2.0)\n", "Requirement already satisfied: async-timeout<4.0,>=3.0 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from aiohttp==3.7.4->alpaca-trade-api) (3.0.1)\n", "Requirement already satisfied: pytz>=2017.3 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from pandas>=0.18.1->alpaca-trade-api) (2021.3)\n", "Requirement already satisfied: python-dateutil>=2.7.3 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from pandas>=0.18.1->alpaca-trade-api) (2.8.2)\n", "Requirement already satisfied: six>=1.5 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from python-dateutil>=2.7.3->pandas>=0.18.1->alpaca-trade-api) (1.16.0)\n", "Requirement already satisfied: charset-normalizer~=2.0.0 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from requests<3,>2->alpaca-trade-api) (2.0.7)\n", "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from requests<3,>2->alpaca-trade-api) (2021.10.8)\n", "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from requests<3,>2->alpaca-trade-api) (3.3)\n" ] } ], "source": [ "!pip install alpaca-trade-api" ] }, { "cell_type": "code", "execution_count": 2, "id": "92a36a11", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: TA-lib in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (0.4.19)\n", "Requirement already satisfied: numpy in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (from TA-lib) (1.21.4)\n" ] } ], "source": [ "!pip install TA-lib" ] }, { "cell_type": "code", "execution_count": 1, "id": "a6491014", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: websocket-client in c:\\users\\lenovo\\anaconda3\\envs\\alpaca_trader\\lib\\site-packages (1.2.3)\n" ] } ], "source": [ "!pip install websocket-client" ] }, { "cell_type": "code", "execution_count": 3, "id": "1373d9df", "metadata": {}, "outputs": [], "source": [ "import alpaca_trade_api as tradeapi\n", "import ast\n", "import json\n", "import numpy as np\n", "import talib as ta\n", "import websocket" ] }, { "cell_type": "markdown", "id": "f1de1e69", "metadata": {}, "source": [ "## Prepare your data for authentication and authenticate your bot at Alpaca" ] }, { "cell_type": "code", "execution_count": 4, "id": "2324ee9c", "metadata": {}, "outputs": [], "source": [ "KEY_ID = \"PK3O8OD82FIXEEPGT8GP\"\n", "SECRET_KEY = \"9tCxXfAtHpeUi6qlhdL9i7dGHt6qgDCNzQreBkcZ\"" ] }, { "cell_type": "code", "execution_count": 5, "id": "864f7768", "metadata": {}, "outputs": [], "source": [ "api = tradeapi.REST(KEY_ID, SECRET_KEY, \"https://paper-api.alpaca.markets\", \"v2\")" ] }, { "cell_type": "markdown", "id": "81a8f3b7", "metadata": {}, "source": [ "## Create variables you might want to change in the future to modify your bot's performance" ] }, { "cell_type": "code", "execution_count": 6, "id": "88f68471", "metadata": {}, "outputs": [], "source": [ "rsi_timeframe = 3\n", "oversold_threshold = 49\n", "overbought_threshold = 51\n", "company = \"AAPL\"\n", "shares = 10\n", "data = []" ] }, { "cell_type": "markdown", "id": "f996032f", "metadata": {}, "source": [ "## Create all the necessary functions" ] }, { "cell_type": "code", "execution_count": 8, "id": "323ff551", "metadata": {}, "outputs": [], "source": [ "def on_open(ws):\n", " auth_data = {\"action\": \"authenticate\", \"data\": {\"key_id\": KEY_ID, \"secret_key\": SECRET_KEY}}\n", " ws.send(json.dumps(auth_data))\n", " \n", " listen_message = {\"action\": \"listen\", \"data\": {\"streams\": [\"AM.\" + company]}}\n", " ws.send(json.dumps(listen_message))\n", " print(\"I'm connected to Alpaca API and ready to work. I'm starting to watch the prices.\")\n", " print(\"I will start calculating RSIs when I'll collect {} prices.\".format(rsi_timeframe))\n", " print(\"I will buy {} shares of {} when the last RSI is less than {}.\".format(shares, company, oversold_threshold))\n", " print(\"I will sell {} shares of {} when the last RSI is more than {}.\".format(shares, company, overbought_threshold))\n", " print(\"So, here we go. Wish me luck.\")\n", " print()" ] }, { "cell_type": "code", "execution_count": 10, "id": "c1346080", "metadata": {}, "outputs": [], "source": [ "def on_message(ws, message):\n", " formatted_message = ast.literal_eval(message)\n", " last_close = formatted_message.get(\"data\").get(\"c\")\n", " print(\"Last price after minute closed: {}$\".format(last_close))\n", " \n", " if isinstance(last_close, float):\n", " data.append(last_close)\n", " print('List of last {} collected prices: {}'.format(rsi_timeframe, data[-rsi_timeframe:]))\n", " \n", " try:\n", " if len(data) > rsi_timeframe:\n", " np_data = np.array(data)\n", " rsis = ta.RSI(np_data, rsi_timeframe)\n", " rsi_now = rsis[-1]\n", " \n", " print(\"The list of last 5 RSIs:\", rsis[-5:])\n", " print(\"Last RSI: \", rsi_now)\n", " \n", " if rsi_now < oversold_threshold:\n", " try:\n", " api.get_position(company)\n", " print(\"We hit the threshold to buy, but we already have some shares, so we won't buy more.\")\n", " except:\n", " api.submit_order(symbol=company, qty=shares, side = \"buy\", type='market', time_in_force='gtc')\n", " print('We submitted the order to buy {} {} shares.'.format(shares, company))\n", " \n", " elif rsi_now > overbought_threshold:\n", " try:\n", " api.get_position(company)\n", " api.submit_order(symbol=company,qty=shares,side='sell',type='market',time_in_force='gtc')\n", " print('We submitted an order to sell {} {} shares.'.format(shares, company))\n", " except:\n", " print(\"We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\")\n", " \n", " else:\n", " print(\"The RSI is {} and it's between the given thresholds: {} and {}, so we wait.\".format(rsi_now, oversold_threshold, overbought_threshold))\n", " else:\n", " print(\"Not enough prices to calculate RSI and start trading:\", len(data), \"<=\", rsi_timeframe)\n", " except:\n", " print(\"I tried my best, buy I think something went wrong. I'll try again in a moment.\")\n", " print()" ] }, { "cell_type": "markdown", "id": "7052ad6d", "metadata": {}, "source": [ "## Connect to websocket and ask your bot nicely to start buying and selling stocks for you" ] }, { "cell_type": "code", "execution_count": 11, "id": "1aae3536", "metadata": {}, "outputs": [], "source": [ "socket = \"wss://data.alpaca.markets/stream\"\n", "SuperAI_trader = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message)" ] }, { "cell_type": "code", "execution_count": 12, "id": "2ccf3868", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I'm connected to Alpaca API and ready to work. I'm starting to watch the prices.\n", "I will start calculating RSIs when I'll collect 3 prices.\n", "I will buy 10 shares of AAPL when the last RSI is less than 49.\n", "I will sell 10 shares of AAPL when the last RSI is more than 51.\n", "So, here we go. Wish me luck.\n", "\n", "Last price after minute closed: None$\n", "Not enough prices to calculate RSI and start trading: 0 <= 3\n", "\n", "Last price after minute closed: None$\n", "Not enough prices to calculate RSI and start trading: 0 <= 3\n", "\n", "Last price after minute closed: 175.295$\n", "List of last 3 collected prices: [175.295]\n", "Not enough prices to calculate RSI and start trading: 1 <= 3\n", "\n", "Last price after minute closed: 175.38$\n", "List of last 3 collected prices: [175.295, 175.38]\n", "Not enough prices to calculate RSI and start trading: 2 <= 3\n", "\n", "Last price after minute closed: 175.415$\n", "List of last 3 collected prices: [175.295, 175.38, 175.415]\n", "Not enough prices to calculate RSI and start trading: 3 <= 3\n", "\n", "Last price after minute closed: 175.38$\n", "List of last 3 collected prices: [175.38, 175.415, 175.38]\n", "The list of last 5 RSIs: [ nan nan nan 77.41935484]\n", "Last RSI: 77.41935483871205\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 175.765$\n", "List of last 3 collected prices: [175.415, 175.38, 175.765]\n", "The list of last 5 RSIs: [ nan nan nan 77.41935484 95.221843 ]\n", "Last RSI: 95.22184300341335\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 175.76$\n", "List of last 3 collected prices: [175.38, 175.765, 175.76]\n", "The list of last 5 RSIs: [ nan nan 77.41935484 95.221843 93.78151261]\n", "Last RSI: 93.78151260504366\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 175.91$\n", "List of last 3 collected prices: [175.765, 175.76, 175.91]\n", "The list of last 5 RSIs: [ nan 77.41935484 95.221843 93.78151261 96.3 ]\n", "Last RSI: 96.30000000000108\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 175.825$\n", "List of last 3 collected prices: [175.76, 175.91, 175.825]\n", "The list of last 5 RSIs: [77.41935484 95.221843 93.78151261 96.3 71.63846011]\n", "Last RSI: 71.63846010786588\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 175.9$\n", "List of last 3 collected prices: [175.91, 175.825, 175.9]\n", "The list of last 5 RSIs: [95.221843 93.78151261 96.3 71.63846011 78.81797347]\n", "Last RSI: 78.81797347038027\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 176$\n", "The list of last 5 RSIs: [95.221843 93.78151261 96.3 71.63846011 78.81797347]\n", "Last RSI: 78.81797347038027\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 175.95$\n", "List of last 3 collected prices: [175.825, 175.9, 175.95]\n", "The list of last 5 RSIs: [93.78151261 96.3 71.63846011 78.81797347 83.09687431]\n", "Last RSI: 83.09687430724783\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 176.155$\n", "List of last 3 collected prices: [175.9, 175.95, 176.155]\n", "The list of last 5 RSIs: [96.3 71.63846011 78.81797347 83.09687431 92.46183029]\n", "Last RSI: 92.46183029232013\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 175.9$\n", "List of last 3 collected prices: [175.95, 176.155, 175.9]\n", "The list of last 5 RSIs: [71.63846011 78.81797347 83.09687431 92.46183029 45.46367369]\n", "Last RSI: 45.463673691359155\n", "We submitted the order to buy 10 AAPL shares.\n", "\n", "Last price after minute closed: 175.78$\n", "List of last 3 collected prices: [176.155, 175.9, 175.78]\n", "The list of last 5 RSIs: [78.81797347 83.09687431 92.46183029 45.46367369 33.45873025]\n", "Last RSI: 33.45873025278052\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 175.98$\n", "List of last 3 collected prices: [175.9, 175.78, 175.98]\n", "The list of last 5 RSIs: [83.09687431 92.46183029 45.46367369 33.45873025 59.91826169]\n", "Last RSI: 59.91826169053701\n", "We submitted an order to sell 10 AAPL shares.\n", "\n", "You've interrupted me. That's it then. I hope I did good. Till the next time.\n" ] } ], "source": [ "SuperAI_trader.run_forever()\n", "print(\"You've interrupted me. That's it then. I hope I did good. Till the next time.\")" ] }, { "cell_type": "markdown", "id": "5bc6b573", "metadata": {}, "source": [ "## Modify the bot" ] }, { "cell_type": "code", "execution_count": 13, "id": "75fd662e", "metadata": {}, "outputs": [], "source": [ "rsi_timeframe = 4\n", "oversold_threshold = 48\n", "overbought_threshold = 52\n", "company = \"TSLA\"\n", "shares = 100\n", "data = []" ] }, { "cell_type": "code", "execution_count": 14, "id": "49773910", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I'm connected to Alpaca API and ready to work. I'm starting to watch the prices.\n", "I will start calculating RSIs when I'll collect 4 prices.\n", "I will buy 100 shares of TSLA when the last RSI is less than 48.\n", "I will sell 100 shares of TSLA when the last RSI is more than 52.\n", "So, here we go. Wish me luck.\n", "\n", "Last price after minute closed: None$\n", "Not enough prices to calculate RSI and start trading: 0 <= 4\n", "\n", "Last price after minute closed: None$\n", "Not enough prices to calculate RSI and start trading: 0 <= 4\n", "\n", "Last price after minute closed: 958.83$\n", "List of last 4 collected prices: [958.83]\n", "Not enough prices to calculate RSI and start trading: 1 <= 4\n", "\n", "Last price after minute closed: 957.835$\n", "List of last 4 collected prices: [958.83, 957.835]\n", "Not enough prices to calculate RSI and start trading: 2 <= 4\n", "\n", "Last price after minute closed: 958.57$\n", "List of last 4 collected prices: [958.83, 957.835, 958.57]\n", "Not enough prices to calculate RSI and start trading: 3 <= 4\n", "\n", "Last price after minute closed: 954.18$\n", "List of last 4 collected prices: [958.83, 957.835, 958.57, 954.18]\n", "Not enough prices to calculate RSI and start trading: 4 <= 4\n", "\n", "Last price after minute closed: 953.69$\n", "List of last 4 collected prices: [957.835, 958.57, 954.18, 953.69]\n", "The list of last 5 RSIs: [ nan nan nan nan 11.11951589]\n", "Last RSI: 11.119515885022876\n", "We submitted the order to buy 100 TSLA shares.\n", "\n", "Last price after minute closed: 950.56$\n", "List of last 4 collected prices: [958.57, 954.18, 953.69, 950.56]\n", "The list of last 5 RSIs: [ nan nan nan 11.11951589 6.81607419]\n", "Last RSI: 6.816074188562622\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 952.15$\n", "List of last 4 collected prices: [954.18, 953.69, 950.56, 952.15]\n", "The list of last 5 RSIs: [ nan nan 11.11951589 6.81607419 26.16948322]\n", "Last RSI: 26.169483223120356\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 950.42$\n", "List of last 4 collected prices: [953.69, 950.56, 952.15, 950.42]\n", "The list of last 5 RSIs: [ nan 11.11951589 6.81607419 26.16948322 20.11020724]\n", "Last RSI: 20.110207239800182\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 948.42$\n", "List of last 4 collected prices: [950.56, 952.15, 950.42, 948.42]\n", "The list of last 5 RSIs: [11.11951589 6.81607419 26.16948322 20.11020724 14.82068459]\n", "Last RSI: 14.820684588789643\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 949$\n", "The list of last 5 RSIs: [11.11951589 6.81607419 26.16948322 20.11020724 14.82068459]\n", "Last RSI: 14.820684588789643\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 948.89$\n", "List of last 4 collected prices: [952.15, 950.42, 948.42, 948.89]\n", "The list of last 5 RSIs: [ 6.81607419 26.16948322 20.11020724 14.82068459 21.30623526]\n", "Last RSI: 21.306235257452162\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 947.78$\n", "List of last 4 collected prices: [950.42, 948.42, 948.89, 947.78]\n", "The list of last 5 RSIs: [26.16948322 20.11020724 14.82068459 21.30623526 17.1857753 ]\n", "Last RSI: 17.185775300484863\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 947.5$\n", "List of last 4 collected prices: [948.42, 948.89, 947.78, 947.5]\n", "The list of last 5 RSIs: [20.11020724 14.82068459 21.30623526 17.1857753 16.13619901]\n", "Last RSI: 16.13619901243597\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 949.84$\n", "List of last 4 collected prices: [948.89, 947.78, 947.5, 949.84]\n", "The list of last 5 RSIs: [14.82068459 21.30623526 17.1857753 16.13619901 50.09654278]\n", "Last RSI: 50.096542782902546\n", "The RSI is 50.096542782902546 and it's between the given thresholds: 48 and 52, so we wait.\n", "\n", "Last price after minute closed: 947.94$\n", "List of last 4 collected prices: [947.78, 947.5, 949.84, 947.94]\n", "The list of last 5 RSIs: [21.30623526 17.1857753 16.13619901 50.09654278 34.82787874]\n", "Last RSI: 34.82787873764192\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 948.97$\n", "List of last 4 collected prices: [947.5, 949.84, 947.94, 948.97]\n", "The list of last 5 RSIs: [17.1857753 16.13619901 50.09654278 34.82787874 46.59338672]\n", "Last RSI: 46.59338671535519\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 949.33$\n", "List of last 4 collected prices: [949.84, 947.94, 948.97, 949.33]\n", "The list of last 5 RSIs: [16.13619901 50.09654278 34.82787874 46.59338672 50.73783155]\n", "Last RSI: 50.73783155085937\n", "The RSI is 50.73783155085937 and it's between the given thresholds: 48 and 52, so we wait.\n", "\n", "Last price after minute closed: 947.97$\n", "List of last 4 collected prices: [947.94, 948.97, 949.33, 947.97]\n", "The list of last 5 RSIs: [50.09654278 34.82787874 46.59338672 50.73783155 36.47887123]\n", "Last RSI: 36.478871231662936\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 945.05$\n", "List of last 4 collected prices: [948.97, 949.33, 947.97, 945.05]\n", "The list of last 5 RSIs: [34.82787874 46.59338672 50.73783155 36.47887123 20.21523956]\n", "Last RSI: 20.215239559532506\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 946.03$\n", "List of last 4 collected prices: [949.33, 947.97, 945.05, 946.03]\n", "The list of last 5 RSIs: [46.59338672 50.73783155 36.47887123 20.21523956 33.48537222]\n", "Last RSI: 33.485372222938445\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 946.94$\n", "List of last 4 collected prices: [947.97, 945.05, 946.03, 946.94]\n", "The list of last 5 RSIs: [50.73783155 36.47887123 20.21523956 33.48537222 44.8434853 ]\n", "Last RSI: 44.8434853006102\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 944.46$\n", "List of last 4 collected prices: [945.05, 946.03, 946.94, 944.46]\n", "The list of last 5 RSIs: [36.47887123 20.21523956 33.48537222 44.8434853 27.67271403]\n", "Last RSI: 27.67271402670053\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 939.67$\n", "List of last 4 collected prices: [946.03, 946.94, 944.46, 939.67]\n", "The list of last 5 RSIs: [20.21523956 33.48537222 44.8434853 27.67271403 13.93331927]\n", "Last RSI: 13.933319268482036\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 941.56$\n", "List of last 4 collected prices: [946.94, 944.46, 939.67, 941.56]\n", "The list of last 5 RSIs: [33.48537222 44.8434853 27.67271403 13.93331927 31.75835344]\n", "Last RSI: 31.75835344391703\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 940.36$\n", "List of last 4 collected prices: [944.46, 939.67, 941.56, 940.36]\n", "The list of last 5 RSIs: [44.8434853 27.67271403 13.93331927 31.75835344 27.0208225 ]\n", "Last RSI: 27.020822496033226\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 939.59$\n", "List of last 4 collected prices: [939.67, 941.56, 940.36, 939.59]\n", "The list of last 5 RSIs: [27.67271403 13.93331927 31.75835344 27.0208225 23.9625553 ]\n", "Last RSI: 23.962555301372106\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 938.2$\n", "List of last 4 collected prices: [941.56, 940.36, 939.59, 938.2]\n", "The list of last 5 RSIs: [13.93331927 31.75835344 27.0208225 23.9625553 18.83226231]\n", "Last RSI: 18.83226231322911\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 935.95$\n", "List of last 4 collected prices: [940.36, 939.59, 938.2, 935.95]\n", "The list of last 5 RSIs: [31.75835344 27.0208225 23.9625553 18.83226231 12.88047528]\n", "Last RSI: 12.880475279958514\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 937.8$\n", "List of last 4 collected prices: [939.59, 938.2, 935.95, 937.8]\n", "The list of last 5 RSIs: [27.0208225 23.9625553 18.83226231 12.88047528 35.29811052]\n", "Last RSI: 35.298110522462956\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 935.37$\n", "List of last 4 collected prices: [938.2, 935.95, 937.8, 935.37]\n", "The list of last 5 RSIs: [23.9625553 18.83226231 12.88047528 35.29811052 24.33247392]\n", "Last RSI: 24.332473920547187\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 937.985$\n", "List of last 4 collected prices: [935.95, 937.8, 935.37, 937.985]\n", "The list of last 5 RSIs: [18.83226231 12.88047528 35.29811052 24.33247392 47.66191652]\n", "Last RSI: 47.66191652250448\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 937.86$\n", "List of last 4 collected prices: [937.8, 935.37, 937.985, 937.86]\n", "The list of last 5 RSIs: [12.88047528 35.29811052 24.33247392 47.66191652 46.74338919]\n", "Last RSI: 46.743389194037455\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 937.44$\n", "List of last 4 collected prices: [935.37, 937.985, 937.86, 937.44]\n", "The list of last 5 RSIs: [35.29811052 24.33247392 47.66191652 46.74338919 43.02842963]\n", "Last RSI: 43.02842963141346\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 937.8$\n", "List of last 4 collected prices: [937.985, 937.86, 937.44, 937.8]\n", "The list of last 5 RSIs: [24.33247392 47.66191652 46.74338919 43.02842963 47.77223919]\n", "Last RSI: 47.77223919119988\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 937.63$\n", "List of last 4 collected prices: [937.86, 937.44, 937.8, 937.63]\n", "The list of last 5 RSIs: [47.66191652 46.74338919 43.02842963 47.77223919 45.39245339]\n", "Last RSI: 45.392453390419405\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 936.81$\n", "List of last 4 collected prices: [937.44, 937.8, 937.63, 936.81]\n", "The list of last 5 RSIs: [46.74338919 43.02842963 47.77223919 45.39245339 34.37831508]\n", "Last RSI: 34.37831507608808\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 935.38$\n", "List of last 4 collected prices: [937.8, 937.63, 936.81, 935.38]\n", "The list of last 5 RSIs: [43.02842963 47.77223919 45.39245339 34.37831508 21.97830593]\n", "Last RSI: 21.97830592631813\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 935.02$\n", "List of last 4 collected prices: [937.63, 936.81, 935.38, 935.02]\n", "The list of last 5 RSIs: [47.77223919 45.39245339 34.37831508 21.97830593 19.60472827]\n", "Last RSI: 19.604728269782225\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 935.92$\n", "List of last 4 collected prices: [936.81, 935.38, 935.02, 935.92]\n", "The list of last 5 RSIs: [45.39245339 34.37831508 21.97830593 19.60472827 40.88530629]\n", "Last RSI: 40.88530628529858\n", "We hit the threshold to buy, but we already have some shares, so we won't buy more.\n", "\n", "Last price after minute closed: 938.41$\n", "List of last 4 collected prices: [935.38, 935.02, 935.92, 938.41]\n", "The list of last 5 RSIs: [34.37831508 21.97830593 19.60472827 40.88530629 70.09041659]\n", "Last RSI: 70.09041658962548\n", "We submitted an order to sell 100 TSLA shares.\n", "\n", "Last price after minute closed: 938.72$\n", "List of last 4 collected prices: [935.02, 935.92, 938.41, 938.72]\n", "The list of last 5 RSIs: [21.97830593 19.60472827 40.88530629 70.09041659 72.35737606]\n", "Last RSI: 72.35737606116118\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 939.68$\n", "List of last 4 collected prices: [935.92, 938.41, 938.72, 939.68]\n", "The list of last 5 RSIs: [19.60472827 40.88530629 70.09041659 72.35737606 78.9462492 ]\n", "Last RSI: 78.94624920021882\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 938.945$\n", "List of last 4 collected prices: [938.41, 938.72, 939.68, 938.945]\n", "The list of last 5 RSIs: [40.88530629 70.09041659 72.35737606 78.9462492 63.49606862]\n", "Last RSI: 63.496068624751146\n", "We hit the threshold to sell, but we don't have anything to sell. Next time maybe.\n", "\n", "Last price after minute closed: 937.57$\n", "List of last 4 collected prices: [938.72, 939.68, 938.945, 937.57]\n", "The list of last 5 RSIs: [70.09041659 72.35737606 78.9462492 63.49606862 42.66769575]\n", "Last RSI: 42.66769575403991\n", "We submitted the order to buy 100 TSLA shares.\n", "\n", "Last price after minute closed: 939.1$\n", "List of last 4 collected prices: [939.68, 938.945, 937.57, 939.1]\n", "The list of last 5 RSIs: [72.35737606 78.9462492 63.49606862 42.66769575 61.43579697]\n", "Last RSI: 61.43579697420961\n", "We submitted an order to sell 100 TSLA shares.\n", "\n", "You've interrupted me. That's it then. I hope I did good. Till the next time.\n" ] } ], "source": [ "SuperAI_trader.run_forever()\n", "print(\"You've interrupted me. That's it then. I hope I did good. Till the next time.\")" ] }, { "cell_type": "markdown", "id": "148fd3ee", "metadata": {}, "source": [ "### Pretty much the same bot in 15 lines of code" ] }, { "cell_type": "code", "execution_count": 16, "id": "fd6dabe2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import alpaca_trade_api as tradeapi, ast, json, numpy as np, talib as ta, websocket\n", "data = []\n", "def on_open(ws):\n", " ws.send(json.dumps({\"action\": \"authenticate\", \"data\": {\"key_id\": \"PK3O8OD82FIXEEPGT8GP\", \"secret_key\": \"9tCxXfAtHpeUi6qlhdL9i7dGHt6qgDCNzQreBkcZ\"}}))\n", " ws.send(json.dumps({\"action\": \"listen\", \"data\": {\"streams\": [\"AM.AAPL\"]}}))\n", "def on_message(ws, message):\n", " if isinstance(ast.literal_eval(message).get(\"data\").get(\"c\"), float): data.append(ast.literal_eval(message).get(\"data\").get(\"c\")) \n", " if len(data) > 3 and ta.RSI(np.array(data), 3)[-1] < 49:\n", " try: tradeapi.REST(\"PK3O8OD82FIXEEPGT8GP\", \"9tCxXfAtHpeUi6qlhdL9i7dGHt6qgDCNzQreBkcZ\", \"https://paper-api.alpaca.markets\", \"v2\").get_position(\"AAPL\")\n", " except:tradeapi.REST(\"PK3O8OD82FIXEEPGT8GP\", \"9tCxXfAtHpeUi6qlhdL9i7dGHt6qgDCNzQreBkcZ\", \"https://paper-api.alpaca.markets\", \"v2\").submit_order(symbol=\"AAPL\", qty=10, side = \"buy\", type='market', time_in_force='gtc') \n", " elif len(data) > 3 and ta.RSI(np.array(data), 3)[-1] > 51:\n", " tradeapi.REST(\"PK3O8OD82FIXEEPGT8GP\", \"9tCxXfAtHpeUi6qlhdL9i7dGHt6qgDCNzQreBkcZ\", \"https://paper-api.alpaca.markets\", \"v2\").get_position(\"AAPL\")\n", " tradeapi.REST(\"PK3O8OD82FIXEEPGT8GP\", \"9tCxXfAtHpeUi6qlhdL9i7dGHt6qgDCNzQreBkcZ\", \"https://paper-api.alpaca.markets\", \"v2\").submit_order(symbol=\"AAPL\",qty=10,side='sell',type='market',time_in_force='gtc')\n", "websocket.WebSocketApp(\"wss://data.alpaca.markets/stream\", on_open=on_open, on_message=on_message).run_forever()" ] }, { "cell_type": "code", "execution_count": null, "id": "9c9efd5e", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }