├── Pairs_Trading_Algo_Example.py └── README.md /Pairs_Trading_Algo_Example.py: -------------------------------------------------------------------------------- 1 | import os 2 | import alpaca_trade_api as tradeapi 3 | import pandas as pd 4 | import smtplib 5 | from email.mime.multipart import MIMEMultipart 6 | from email.mime.text import MIMEText 7 | 8 | 9 | def pairs_trading_algo(self): 10 | 11 | #Specify paper trading environment 12 | os.environ["APCA_API_BASE_URL"] = "https://paper-api.alpaca.markets" 13 | #Insert API Credentials 14 | api = tradeapi.REST('API_KEY_ID', 'API_SECRET_KEY', api_version='v2') # or use ENV Vars shown below 15 | account = api.get_account() 16 | 17 | #The mail addresses and password 18 | sender_address = 'trading.algo15@gmail.com' 19 | sender_pass = '**********' 20 | receiver_address = 'mcklayne.marshall@gmail.com' 21 | #Setup the MIME 22 | message = MIMEMultipart() 23 | message['From'] = 'Trading Bot' 24 | message['To'] = receiver_address 25 | message['Subject'] = 'Pairs Trading Algo' #The subject line 26 | 27 | #Selection of stocks 28 | days = 1000 29 | stock1 = 'ADBE' 30 | stock2 = 'AAPL' 31 | #Put Hisrorical Data into variables 32 | stock1_barset = api.get_barset(stock1,'day',limit=days) 33 | stock2_barset = api.get_barset(stock2,'day',limit=days) 34 | stock1_bars = stock1_barset[stock1] 35 | stock2_bars = stock2_barset[stock2] 36 | #Grab stock1 data and put in to a array 37 | data_1 = [] 38 | times_1 = [] 39 | for i in range(days): 40 | stock1_close = stock1_bars[i].c 41 | stock1_time = stock1_bars[i].t 42 | data_1.append(stock1_close) 43 | times_1.append(stock1_time) 44 | #Grab stock2 data and put in to an array 45 | data_2 = [] 46 | times_2 = [] 47 | for i in range(days): 48 | stock2_close = stock2_bars[i].c 49 | stock2_time = stock1_bars[i].t 50 | data_2.append(stock2_close) 51 | times_2.append(stock2_time) 52 | #Putting them together 53 | hist_close = pd.DataFrame(data_1, columns=[stock1]) 54 | hist_close[stock2] = data_2 55 | #Current Spread between the two stocks 56 | stock1_curr = data_1[days-1] 57 | stock2_curr = data_2[days-1] 58 | spread_curr = (stock1_curr-stock2_curr) 59 | #Moving Average of the two stocks 60 | move_avg_days = 5 61 | #Moving averge for stock1 62 | stock1_last = [] 63 | for i in range(move_avg_days): 64 | stock1_last.append(data_1[(days-1)-i]) 65 | 66 | stock1_hist = pd.DataFrame(stock1_last) 67 | 68 | stock1_mavg = stock1_hist.mean() 69 | #Moving average for stock2 70 | stock2_last = [] 71 | for i in range(move_avg_days): 72 | stock2_last.append(data_2[(days-1)-i]) 73 | stock2_hist = pd.DataFrame(stock2_last) 74 | stock2_mavg = stock2_hist.mean() 75 | #Sread_avg 76 | spread_avg = min(stock1_mavg - stock2_mavg) 77 | #Spread_factor 78 | spreadFactor = .01 79 | wideSpread = spread_avg*(1+spreadFactor) 80 | thinSpread = spread_avg*(1-spreadFactor) 81 | #Calc_of_shares_to_trade 82 | cash = float(account.buying_power) 83 | limit_stock1 = cash//stock1_curr 84 | limit_stock2 = cash//stock2_curr 85 | number_of_shares = int(min(limit_stock1, limit_stock2)/2) 86 | 87 | #Trading_algo 88 | portfolio = api.list_positions() 89 | clock = api.get_clock() 90 | 91 | if clock.is_open == True: 92 | if bool(portfolio) == False: 93 | #detect a wide spread 94 | if spread_curr > wideSpread: 95 | #short top stock 96 | api.submit_order(symbol = stock1,qty = number_of_shares,side = 'sell',type = 'market',time_in_force ='day') 97 | #Long bottom stock 98 | api.submit_order(symbol = stock2,qty = number_of_shares,side = 'buy',type = 'market',time_in_force = 'day') 99 | mail_content = "Trades have been made, short top stock and long bottom stock" 100 | #detect a tight spread 101 | elif spread_curr < thinSpread: 102 | #long top stock 103 | api.submit_order(symbol = stock1,qty = number_of_shares,side = 'buy',type = 'market',time_in_force = 'day') 104 | #short bottom stock 105 | api.submit_order(symbol = stock2,qty = number_of_shares,side = 'sell',type = 'market',time_in_force ='day') 106 | mail_content = "Trades have been made, long top stock and short bottom stock" 107 | else: 108 | wideTradeSpread = spread_avg *(1+spreadFactor + .03) 109 | thinTradeSpread = spread_avg *(1+spreadFactor - .03) 110 | if spread_curr <= wideTradeSpread and spread_curr >=thinTradeSpread: 111 | api.close_position(stock1) 112 | api.close_position(stock2) 113 | mail_content = "Position has been closed" 114 | else: 115 | mail_content = "No trades were made, position remains open" 116 | pass 117 | else: 118 | mail_content = "The Market is Closed" 119 | 120 | #The body and the attachments for the mail 121 | message.attach(MIMEText(mail_content, 'plain')) 122 | #Create SMTP session for sending the mail 123 | session = smtplib.SMTP('smtp.gmail.com', 587) #use gmail with port 124 | session.starttls() #enable security 125 | session.login(sender_address, sender_pass) #login with mail_id and password 126 | text = message.as_string() 127 | session.sendmail(sender_address, receiver_address, text) 128 | session.quit() 129 | 130 | done = 'Mail Sent' 131 | 132 | return done -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # automate_algo_trading_medium 2 | Python script for medium article 3 | --------------------------------------------------------------------------------