├── README.md ├── ec2VWAPFiveMinReco.R ├── pyVwapDataUpdater_start.sh ├── pyVwapDataUpdater_stop.sh └── vwapDataUpdater.py /README.md: -------------------------------------------------------------------------------- 1 | # pyVWAPTradingSignalSystem 2 | A Python system to generate Volume Weighted Average Pricing (VWAP) Model based Long/Short Trading Signal 3 | -------------------------------------------------------------------------------- /ec2VWAPFiveMinReco.R: -------------------------------------------------------------------------------- 1 | #hostName <- "localhost" 2 | hostName <- "172.31.32.173" 3 | dbName <- "StocksDB" 4 | tbName <- "VWAPFiveMinTable" 5 | stockPriceXtsLol <- list() 6 | stockPriceFiveMinXtsList <- list() 7 | TradeFiveMinList <- list() 8 | ClosePriceList <- list() 9 | 10 | sql_conn <- dbConnect(MySQL(), user = "root", password = "", dbname = dbName, host = hostName) 11 | symbol_sql_command <- paste("SELECT DISTINCT GoogleCode FROM ", tbName, sep = "") 12 | symbol_sql_result <- dbGetQuery(sql_conn, symbol_sql_command) 13 | dbDisconnect(sql_conn) 14 | for(i in 1:length(symbol_sql_result[,1])){ 15 | symbol <- symbol_sql_result[i,] 16 | sql_conn <- dbConnect(MySQL(), user = "root", password = "", dbname = dbName, host = hostName) 17 | quote_sql_command <- paste("SELECT Date, Time, Open, High, Low, Close, Volume FROM ", dbName, ".", 18 | tbName, " WHERE GoogleCode = '", symbol, "';", sep = "") 19 | quote_sql_result <- dbGetQuery(sql_conn, quote_sql_command) 20 | dbDisconnect(sql_conn) 21 | dateTime <- paste(quote_sql_result$Date, quote_sql_result$Time, sep = " ") 22 | timeIndx <- strptime(dateTime, format = "%Y-%m-%d %H:%M:%S") 23 | prices <- quote_sql_result[, c("Open", "High", "Low", "Close", "Volume")] 24 | stockPriceFiveMinXtsList[[symbol]] <- as.xts(prices, timeIndx) 25 | } 26 | stockPriceXtsLol[["IntradayFiveMinTable"]] <- stockPriceFiveMinXtsList 27 | 28 | for(i in 1:length(stockPriceXtsLol$IntradayFiveMinTable)){ 29 | symbol <- stockPriceXtsLol$IntradayFiveMinTable[[i]] 30 | symbolName <- names(stockPriceXtsLol$IntradayFiveMinTable)[i] 31 | nlookback <- 3 32 | uLim <- 1.001 33 | lLim <- 0.999 34 | time_index <- as.POSIXct(index(symbol), format = "%Y-%m-%d %H:%M:%S") 35 | symbol <- apply(symbol, 2, as.numeric) 36 | symbol <- xts(symbol, time_index) 37 | 38 | vwap <- VWAP(Cl(symbol), Vo(symbol), n=nlookback) 39 | clPrice <- Cl(symbol) 40 | intraBarRet <- Delt(Cl(symbol), k=1, type="arithmetic") 41 | signal <- Cl(symbol) / vwap 42 | signal[is.na(signal)] <- 1 43 | trade <- apply(signal, 1, function(x) { 44 | if(x < lLim) { 45 | return (1) 46 | } else { 47 | if(x > uLim) { 48 | return(-1) 49 | } else { 50 | return (0) 51 | } 52 | } 53 | }) 54 | TradeFiveMinList[[symbolName]] <- as.numeric(trade[length(trade)]) 55 | ClosePriceList[[symbolName]] <- as.numeric(clPrice[length(clPrice)]) 56 | } -------------------------------------------------------------------------------- /pyVwapDataUpdater_start.sh: -------------------------------------------------------------------------------- 1 | /home/ubuntu/tradeStrats/vwap/pyVwapDataUpdater.sh start 2 | -------------------------------------------------------------------------------- /pyVwapDataUpdater_stop.sh: -------------------------------------------------------------------------------- 1 | /home/ubuntu/tradeStrats/vwap/pyVwapDataUpdater.sh stop 2 | -------------------------------------------------------------------------------- /vwapDataUpdater.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | __author__ = 'riteshg' 3 | 4 | import sys 5 | import json 6 | import urllib,time,datetime 7 | import MySQLdb as mdb 8 | from time import sleep 9 | from threading import Thread 10 | import pyRserve 11 | import subprocess 12 | import requests 13 | 14 | # Run Command in EC2: 15 | # nohup python vwapDataUpdater.py & 16 | 17 | # Overall Global Vars 18 | openQuote = "OPEN_QUOTE" 19 | periodicQuote = "PERIODIC_QUOTE" 20 | currTimeQuoteDBUpdateMap = {} 21 | currTimeRExecMap = {} 22 | openingPriceUpdatedStocksList = [] 23 | periodicPriceUpdateDict = {} 24 | # DBserverIP = 'localhost' # DEBUGGING 25 | DBserverIP = '172.31.32.173' 26 | # HTTPServerIp = '52.24.168.159' # DEBUGGING 27 | HTTPServerIp = 'localhost' 28 | 29 | # VWAP Strategy time interval specific global Vars 30 | periodicTimeListFifteenMin = ["09:30", "09:45", "10:00", "10:15", "10:30", "10:45", "11:00", "11:15", 31 | "11:30", "11:45", "12:00", "12:15", "12:30", "12:45", "13:00", "13:15", 32 | "13:30", "13:45", "14:00", "14:15", "14:30", "14:45", "15:00", "15:15"] 33 | periodicTimeListFiveMin = ["09:20", "09:25", "09:30", "09:35", "09:40", "09:45", "09:50", "09:55", "10:00", 34 | "10:05", "10:10", "10:15", "10:20", "10:25", "10:30", "10:35", "10:40", "10:45", "10:50", "10:55", "11:00", 35 | "11:05", "11:10", "11:15", "11:20", "11:25", "11:30", "11:35", "11:40", "11:45", "11:50", "11:55", "12:00", 36 | "12:05", "12:10", "12:15", "12:20", "12:25", "12:30", "12:35", "12:40", "12:45", "12:50", "12:55", "13:00", 37 | "13:05", "13:10", "13:15", "13:20", "13:25", "13:30", "13:35", "13:40", "13:45", "13:50", "13:55", "14:00", 38 | "14:05", "14:10", "14:15", "14:20", "14:25", "14:30", "14:35", "14:40", "14:45", "14:50", "14:55", "15:00", 39 | "15:05", "15:10", "15:15"] 40 | vwap_tb_name = 'VWAPFiveMinTable' 41 | vwap_strategy_time_tb_name = 'IntradayFiveMinTable' 42 | time_interval = 300 43 | periodicTimeList = periodicTimeListFiveMin 44 | prevNumOfTradingDays = '5' 45 | 46 | # R Specific Global Vars 47 | RServeIP = 'localhost' 48 | Rconn = None 49 | RconnStatus = False 50 | #RFILE_VWAP_FIVEMIN_RECO = r'D:\RiteshComputer\Trading\quant_MyRStrats\vwap\ec2VWAPFiveMinReco.R' # DEBUGGING 51 | #RSCRIPT_VWAP_FIVEMIN_TRADE_SIGNAL = 'source("D:\\RiteshComputer\\Trading\\quant_MyRStrats\\vwap\\ec2VWAPFiveMinReco.R")' # DEBUGGING 52 | RFILE_VWAP_FIVEMIN_RECO = r'/home/ubuntu/tradeStrats/vwap/Rcode/ec2VWAPFiveMinReco.R' 53 | RSCRIPT_VWAP_FIVEMIN_TRADE_SIGNAL = 'source("/home/ubuntu/tradeStrats/vwap/Rcode/ec2VWAPFiveMinReco.R")' 54 | 55 | ''' 56 | Quote Class 57 | ''' 58 | class IntradayQuote(object): 59 | # Date and Time Formats 60 | DATE_FMT = '%Y-%m-%d' 61 | TIME_FMT = '%H:%M:%S' 62 | 63 | def __init__(self): 64 | # initializer 65 | self.symbol = '' 66 | self.date, self.time, self.open_, self.high, self.low, self.close, self.volume = ([] for _ in range(7)) 67 | 68 | def append(self, dt, open_, high, low, close, volume): 69 | # Update the fields of the Quote object 70 | self.date.append(dt.date()) # Date 71 | self.time.append(dt.time()) # Time 72 | self.open_.append(float(open_)) # O 73 | self.high.append(float(high)) # H 74 | self.low.append(float(low)) # L 75 | self.close.append(float(close)) # C 76 | self.volume.append(int(volume)) # Vol 77 | 78 | def to_csv(self): 79 | # prepare the comma separated line of the quote 80 | return ''.join(["{0}, {1}, {2}, {3:.2f}, {4:.2f}, {5:.2f}, {6:.2f}, {7}\n".format(self.symbol, 81 | self.date[bar].strftime('%Y-%m-%d'), self.time[bar].strftime('%H:%M:%S'), 82 | self.open_[bar], self.high[bar], self.low[bar], self.close[bar], self.volume[bar]) 83 | for bar in xrange(len(self.close))]) 84 | 85 | def __repr__(self): 86 | # repr of the object 87 | return self.to_csv() 88 | 89 | ''' 90 | Class to collect the intraday quote 91 | from google finance XHR URL 92 | ''' 93 | class GoogleIntradayQuote(IntradayQuote): 94 | ''' 95 | Method to prepare StockQuote from self 96 | ''' 97 | def prepareStockQuoteFromSelfData(self, tick): 98 | stockQuote = {} 99 | stockQuote['symbol'] = self.symbol 100 | stockQuote['date'] = self.date[tick] 101 | stockQuote['time'] = self.time[tick] 102 | stockQuote['open_'] = self.open_[tick] 103 | stockQuote['high'] = self.high[tick] 104 | stockQuote['low'] = self.low[tick] 105 | stockQuote['close'] = self.close[tick] 106 | stockQuote['volume'] = self.volume[tick] 107 | return stockQuote 108 | 109 | ''' 110 | DB update routine of quotes 111 | ''' 112 | def updateDB(self, stockQuote, currTime): 113 | # Connect to the MySQL instance 114 | db_host = DBserverIP 115 | db_user = 'root' 116 | db_pass = '' 117 | db_name = 'StocksDB' # Remove '_' for execution, accidently DB write proof :) 118 | tb_name = vwap_tb_name 119 | 120 | # Connect to DB 121 | # IMPORTANT: DO NOT HANDLE EXCEPTION HERE, R SCRIPT EXEC IS DEPENDENT ON EXCEPTION CHECK 122 | conn = mdb.connect(host=db_host, user=db_user, passwd=db_pass, db=db_name) 123 | # prepare SQL query 124 | sqlQuery = "INSERT INTO " + tb_name + " (GoogleCode, Date, Time, Open, High, Low, Close, Volume, UpdatedTime) " \ 125 | + "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)" 126 | sqlValue = (stockQuote['symbol'], stockQuote['date'].strftime('%Y-%m-%d'), stockQuote['time'].strftime('%H:%M:%S'), 127 | stockQuote['open_'], stockQuote['high'], stockQuote['low'], stockQuote['close'], stockQuote['volume'], 128 | datetime.datetime.now().time().strftime("%H:%M:%S")) 129 | 130 | # Fire Sql Query 131 | cursor = conn.cursor() 132 | cursor.execute(sqlQuery, sqlValue) 133 | # Close SQL connection 134 | conn.commit() 135 | cursor.close() 136 | conn.close() 137 | 138 | # Mark DB Quote update for this stock 139 | currTimeQuoteDBUpdateList = currTimeQuoteDBUpdateMap.get(stockQuote['symbol']) 140 | currTimeQuoteDBUpdateList.append(currTime) 141 | 142 | ''' 143 | Process the intraday Quotes obtained 144 | ''' 145 | def processQuotes(self, stockQuoteList, quoteType, currTime): 146 | if len(stockQuoteList) == 0: 147 | # No added Quotes 148 | return 149 | 150 | if quoteType == openQuote: 151 | # Opening Price Quote 152 | stockQuote = self.prepareStockQuoteFromSelfData(0) 153 | 154 | # Check the time, should be within first 5min 155 | tickTime = stockQuote['time'].strftime('%H:%M:%S') 156 | tickHr = int(tickTime[0:2]) 157 | tickMin = int(tickTime[3:5]) 158 | if tickHr == 9 and tickMin > 14 and tickMin < 20: 159 | # Update Open price if its not already updated 160 | if stockQuote['symbol'] not in openingPriceUpdatedStocksList: 161 | openingPriceUpdatedStocksList.append(stockQuote['symbol']) 162 | # print("OpenQuote => ", stockQuote, file=sys.stderr) # DEBUGGING 163 | self.updateDB(stockQuote, currTime) 164 | elif quoteType == periodicQuote: 165 | # Periodic price Update 166 | stock = self.symbol 167 | # Get the time updated list of this stock 168 | timeUpdateList = periodicPriceUpdateDict.get(stock) 169 | # Go through all the data 170 | for tick in xrange(len(stockQuoteList)): 171 | tickTime = self.time[tick].strftime('%H:%M:%S') 172 | tickHr = int(tickTime[0:2]) 173 | tickMin = int(tickTime[3:5]) 174 | if tick == 0: 175 | # First Quote 176 | # update First Quote if Opening Quote is not updated 177 | if stock not in openingPriceUpdatedStocksList and tickTime not in timeUpdateList: 178 | timeUpdateList.append(tickTime) 179 | stockQuote = self.prepareStockQuoteFromSelfData(tick) 180 | # print("PeriodicQuote 1 => ", stockQuote, file=sys.stderr) # DEBUGGING 181 | self.updateDB(stockQuote, currTime) 182 | # When Opening Quote is already updated, 183 | # Update First Quote from periodic update only after first 5min 184 | elif tickHr == 9 and tickMin >= 20 and tickTime not in timeUpdateList: 185 | timeUpdateList.append(tickTime) 186 | stockQuote = self.prepareStockQuoteFromSelfData(tick) 187 | # print("PeriodicQuote 2 => ", stockQuote, file=sys.stderr) # DEBUGGING 188 | self.updateDB(stockQuote, currTime) 189 | # Update First quote for Special trading days, during non normal trading days 190 | elif tickHr != 9 and tickTime not in timeUpdateList: 191 | timeUpdateList.append(tickTime) 192 | stockQuote = self.prepareStockQuoteFromSelfData(tick) 193 | # print("PeriodicQuote 3 => ", stockQuote, file=sys.stderr) # DEBUGGING 194 | self.updateDB(stockQuote, currTime) 195 | else: 196 | # All other quotes except first 197 | # Do not update after 3:20 closing time 198 | if tickHr == 15 and tickMin >= 20: 199 | # DO NOT UPDATE, DUMMY 200 | stockQuote = self.prepareStockQuoteFromSelfData(tick) 201 | # print("PeriodicQuote 4 => ", stockQuote, file=sys.stderr) # DEBUGGING 202 | # Update the time and data if not present 203 | elif tickTime not in timeUpdateList: 204 | timeUpdateList.append(tickTime) 205 | stockQuote = self.prepareStockQuoteFromSelfData(tick) 206 | # print("PeriodicQuote 5 => ", stockQuote, file=sys.stderr) # DEBUGGING 207 | self.updateDB(stockQuote, currTime) 208 | 209 | ''' 210 | Intraday quotes from Google. 211 | Specify interval seconds and number of days 212 | Default 60 sec interval, 10 days data 213 | ''' 214 | def __init__(self, symbol, interval_seconds=60, num_days=1, quoteType=periodicQuote, currTime='NA'): 215 | super(GoogleIntradayQuote, self).__init__() 216 | # Upper case the symbol 217 | self.symbol = symbol.upper() 218 | # Prepare the URL 219 | url_string = "http://www.google.com/finance/getprices?q={0}".format(self.symbol) 220 | url_string += "&i={0}&p={1}d&f=d,o,h,l,c,v&x=NSE".format(interval_seconds, num_days) 221 | stockQuoteList = [] 222 | # Read the lines from URL 223 | try: 224 | csv = urllib.urlopen(url_string).readlines() 225 | # Leave the first 7 lines from top containing Metadata about the quote 226 | for bar in xrange(7, len(csv)): 227 | # Check if line contains 5 comma separated words 228 | if csv[bar].count(',') != 5 : 229 | continue 230 | # Get the comma separated words 231 | offset, close, high, low, open_, volume = csv[bar].split(',') 232 | if offset[0] == 'a': 233 | # the first word starts with 'a', marking a new day 234 | # strip 'a' to get the timestamp of the day 235 | day = float(offset[1:]) 236 | offset = 0 237 | else: 238 | # if not starts with 'a', its an offset from above timestamp 239 | offset = float(offset) 240 | # Convert OHLC to floats 241 | open_, high, low, close = [float(x) for x in [open_, high, low, close]] 242 | # Calculate the timestamp of the offsets and 243 | # determine the date time from the calculated timestamp 244 | dt = datetime.datetime.fromtimestamp(day + (interval_seconds * offset)) 245 | 246 | # Check the Date 247 | dateToday = datetime.date.today().strftime('%Y-%m-%d') 248 | obtainedDate = dt.date().strftime('%Y-%m-%d') 249 | if dateToday == obtainedDate: 250 | # Update the stock quote list only if the quote is of today's date 251 | self.append(dt, open_, high, low, close, volume) 252 | stockQuoteList.append(self) 253 | except: 254 | print("ERROR: URL OPEN FAILED for GOOGLE FINANCE, URL:[", url_string, "]", file=sys.stderr) 255 | # Process the Quotes List, only when updated 256 | if len(stockQuoteList) > 0: 257 | self.processQuotes(stockQuoteList, quoteType, currTime) 258 | 259 | ''' 260 | Get the stocks for VWAP strategy 261 | ''' 262 | def getStocksForVWAP(forDate, strategyTimeTable): 263 | # Get the Recommended Stocks List from DB 264 | # Connect to the MySQL instance 265 | db_host = DBserverIP 266 | db_user = 'root' 267 | db_pass = '' 268 | db_name = 'StocksDB' # Remove '_' for execution, accidently DB write proof :) 269 | 270 | vwapStocksList = [] 271 | # Connect to DB 272 | conn = mdb.connect(host=db_host, user=db_user, passwd=db_pass, db=db_name) 273 | try: 274 | # prepare SQL query 275 | sqlQuery = "SELECT GoogleCode,Rank FROM VWAPDateWiseRecoStocksTable WHERE TimeIntervalDBTable='" + \ 276 | strategyTimeTable + "' AND Date='" + forDate + "'" 277 | # Fire Sql Query 278 | cursor = conn.cursor() 279 | cursor.execute(sqlQuery) 280 | # Get results 281 | results = cursor.fetchall() 282 | for row in results: 283 | # Update result from Query 284 | stockDict = {} 285 | stockDict['Stock'] = row[0] 286 | stockDict['Rank'] = row[1] 287 | vwapStocksList.append(stockDict) 288 | # Close SQL connection 289 | #conn.commit() # SELECT STATEMENT 290 | except: 291 | print("ERROR: DB SELECT FAILED for SQL Query: ", sqlQuery, file=sys.stderr) 292 | cursor.close() 293 | conn.close() 294 | # Sort it 295 | vwapStocksList = sorted(vwapStocksList, key=lambda k: k['Rank']) 296 | return vwapStocksList 297 | 298 | ''' 299 | Get previous n Intraday trading days 300 | ''' 301 | def getPreviousNTradingDays(): 302 | # Connect to the MySQL instance 303 | db_host = DBserverIP 304 | db_user = 'root' 305 | db_pass = '' 306 | db_name = 'StocksDB' # Remove '_' for execution, accidently DB write proof :) 307 | 308 | dateToday = datetime.date.today().strftime('%Y-%m-%d') 309 | prevDatesList = [] 310 | # Connect to DB 311 | conn = mdb.connect(host=db_host, user=db_user, passwd=db_pass, db=db_name) 312 | try: 313 | # prepare SQL query 314 | sqlQuery = "SELECT Date FROM IntradayTradingDaysTable ORDER BY DayIndxId DESC LIMIT " + prevNumOfTradingDays 315 | # Fire Sql Query 316 | cursor = conn.cursor() 317 | cursor.execute(sqlQuery) 318 | # Get results 319 | results = cursor.fetchall() 320 | for row in results: 321 | # Update result from Query 322 | prevDatesList.append(row[0]) 323 | # Close SQL connection 324 | #conn.commit() # SELECT STATEMENT 325 | except: 326 | print("ERROR: DB SELECT FAILED for SQL Query: ", sqlQuery, file=sys.stderr) 327 | cursor.close() 328 | conn.close() 329 | # Reverse the list (prev days followed by latest days) 330 | prevDatesList.reverse() 331 | 332 | print("Previous Days: ", prevDatesList, file=sys.stderr) 333 | return prevDatesList 334 | 335 | ''' 336 | Update previous Days Data for continuing VWAP strategy 337 | ''' 338 | def updatePreviousData(stockList): 339 | # Get Previous n Days List 340 | prevDatesList = getPreviousNTradingDays() 341 | if len(prevDatesList) == 0: 342 | # No previous trading dates found 343 | return False 344 | 345 | # Exception marker 346 | isExcptnOccured = False 347 | 348 | # Connect to the MySQL instance 349 | db_host = DBserverIP 350 | db_user = 'root' 351 | db_pass = '' 352 | db_name = 'StocksDB' # Remove '_' for execution, accidently DB write proof :) 353 | # Connect to DB 354 | conn = mdb.connect(host=db_host, user=db_user, passwd=db_pass, db=db_name) 355 | try: 356 | cursor = conn.cursor() 357 | # SQL query: Truncate existing data in vwap table 358 | sqlQuery = "TRUNCATE " + vwap_tb_name 359 | cursor.execute(sqlQuery) 360 | conn.commit() 361 | except: 362 | isExcptnOccured = True 363 | print("ERROR: DB TRUNCATE FAILED for SQL Query: ", sqlQuery, file=sys.stderr) 364 | cursor.close() 365 | conn.close() 366 | if isExcptnOccured == True: 367 | # Exception occured in Truncate SQL 368 | return False 369 | 370 | for stock in stockList: 371 | for tradeDate in prevDatesList: 372 | # Connect to the MySQL instance 373 | db_host = DBserverIP 374 | db_user = 'root' 375 | db_pass = '' 376 | db_name = 'StocksDB' # Remove '_' for execution, accidently DB write proof :) 377 | # Connect to DB 378 | conn = mdb.connect(host=db_host, user=db_user, passwd=db_pass, db=db_name) 379 | try: 380 | cursor = conn.cursor() 381 | # SQL query: Get Data from IntradayFifteenMinTable for previous Days 382 | sqlQuery = "INSERT INTO " + vwap_tb_name 383 | sqlQuery += " (GoogleCode, Date, Time, Open, High, Low, Close, Volume)" 384 | sqlQuery += " SELECT GoogleCode, Date, Time, Open, High, Low, Close, Volume" 385 | sqlQuery += " FROM " + vwap_strategy_time_tb_name + " WHERE GoogleCode='" + stock + "' AND Date='" + tradeDate + "'" 386 | cursor.execute(sqlQuery) 387 | conn.commit() 388 | except: 389 | isExcptnOccured = True 390 | print("ERROR: DB INSERT FAILED for SQL Query: ", sqlQuery, file=sys.stderr) 391 | # Close SQL connection 392 | cursor.close() 393 | conn.close() 394 | if isExcptnOccured == True: 395 | # Exception occured in SQL INSERT of previous data 396 | return False 397 | # Previous Days Data Updation Succeeded 398 | return True 399 | 400 | ''' 401 | Update First Quote price of each stock 402 | ''' 403 | def updateTodaysOpenPrice(stockList, currTime): 404 | print("Updating Today's open price", file=sys.stderr) 405 | for stock in stockList: 406 | currTimeQuoteDBUpdateList = currTimeQuoteDBUpdateMap.get(stock.upper()) 407 | if currTime not in currTimeQuoteDBUpdateList: 408 | # For Each interval get Data and Update 409 | q = GoogleIntradayQuote(stock, 60, 1, openQuote, currTime) 410 | # sleep(1) 411 | 412 | ''' 413 | Update All other Quote prices of each stock 414 | ''' 415 | def updateTodaysPeriodicPrice(stockList, currTime): 416 | print("Updating periodic price", file=sys.stderr) 417 | for stock in stockList: 418 | currTimeQuoteDBUpdateList = currTimeQuoteDBUpdateMap.get(stock.upper()) 419 | if currTime not in currTimeQuoteDBUpdateList: 420 | # For Each interval get Data and Update 421 | q = GoogleIntradayQuote(stock, time_interval, 1, periodicQuote, currTime) 422 | # sleep(1) 423 | 424 | ''' 425 | Prepare to dictionary from a given call 426 | ''' 427 | def getCallAddDict(scripName, triggerType, triggerPrice, targetPrice): 428 | #form Dict 429 | dictData = {} 430 | dictData['scrip'] = scripName 431 | dictData['trigger'] = triggerType 432 | dictData['price'] = triggerPrice 433 | dictData['target'] = targetPrice 434 | return dictData 435 | 436 | ''' 437 | send Multi call add JSON data to HTTP method 438 | ''' 439 | def sendHTTPMultiCall(multiCallJSON): 440 | #post to HTTP 441 | post_response = requests.post(url='http://'+ HTTPServerIp +':8080/vwap/fivemin/multicalladded/', data=multiCallJSON) 442 | print('Call Add HTTP Response: ', post_response, file=sys.stderr) 443 | 444 | ''' 445 | Create RServe Conn 446 | ''' 447 | def createRServeConn(): 448 | global Rconn 449 | global RconnStatus 450 | Rconn = pyRserve.connect(host=RServeIP, port=6311) 451 | Rconn.voidEval('library("quantmod")') 452 | Rconn.voidEval('library("PerformanceAnalytics")') 453 | Rconn.voidEval('library("RMySQL")') 454 | Rconn.voidEval('library("xts")') 455 | RconnStatus = True 456 | 457 | ''' 458 | Close RServe Conn 459 | ''' 460 | def closeRServeConn(): 461 | global RconnStatus 462 | Rconn.close() 463 | RconnStatus = False 464 | 465 | ''' 466 | Decide if R code require to be executed 467 | ''' 468 | def checkForRExec(currTime): 469 | for stock in stockList: 470 | currTimeRExecList = currTimeRExecMap.get(stock) 471 | if currTime not in currTimeRExecList: 472 | return True 473 | 474 | ''' 475 | Execute R Script to get Trade Signal from VWAP 476 | ''' 477 | def executeRscriptTradeSignal(currTime): 478 | jsonDataList = [] 479 | # Check If R code to be executed or not 480 | if checkForRExec(currTime) == True: 481 | Rconn.voidEval(RSCRIPT_VWAP_FIVEMIN_TRADE_SIGNAL) 482 | # Get Stock specific VWAP trade call 483 | for stock in stockList: 484 | currTimeQuoteDBUpdateList = currTimeQuoteDBUpdateMap.get(stock.upper()) 485 | currTimeRExecList = currTimeRExecMap.get(stock) 486 | # Fetch VWAP call from R only if DB update happened in currTime, 487 | # But R code VWAP call did not execute for this stock 488 | if currTime in currTimeQuoteDBUpdateList and currTime not in currTimeRExecList: 489 | Rconn.voidEval('signal <- TradeFiveMinList[["' + stock + '"]]') 490 | Rconn.voidEval('currPrice <- ClosePriceList[["' + stock + '"]]') 491 | if Rconn.r.signal == 1: 492 | jsonData = getCallAddDict(stock, 'BUY', str(Rconn.r.currPrice), '0') 493 | jsonDataList.append(jsonData) 494 | elif Rconn.r.signal == -1: 495 | jsonData = getCallAddDict(stock, 'SELL', str(Rconn.r.currPrice), '0') 496 | jsonDataList.append(jsonData) 497 | elif Rconn.r.signal == 0: 498 | jsonData = getCallAddDict(stock, 'SQROFFONLY', str(Rconn.r.currPrice), '0') 499 | jsonDataList.append(jsonData) 500 | # Mark R code execution for this stock 501 | currTimeRExecList.append(currTime) 502 | 503 | # Dont send Blank JSON in HTTP data 504 | if len(jsonDataList) > 0: 505 | # Prepare JSON for the stock 506 | multiCallJsonArr = json.dumps(jsonDataList) 507 | multiCallJSON = '{"callAdded":' + multiCallJsonArr + '}' 508 | # Post the HTTP call 509 | try: 510 | sendHTTPMultiCall(multiCallJSON) 511 | except: 512 | print("ERROR: FAILED TO POST VWAP 5 MIN MULTI CALL", file=sys.stderr) 513 | # Print the call 514 | print(datetime.datetime.now().time().strftime("%H:%M:%S"), ": [VWAP CALL]: <", multiCallJSON, ">", file=sys.stderr) 515 | 516 | ''' 517 | Thread Function for VWAP strategy 518 | ''' 519 | def threadVWAPFunc(): 520 | var = 1 521 | while var == 1: 522 | # Infinite loop of VWAP thread 523 | # Get Current Time 524 | timeNow = datetime.datetime.now().time().strftime("%H:%M:%S") 525 | tickHr = timeNow[0:2] 526 | tickMin = timeNow[3:5] 527 | tickSec = int(timeNow[6:8]) 528 | currTime = tickHr+':'+tickMin 529 | 530 | # Match and Check the time for trigger (HACK: Allow 1 sec for google to update its price: REMOVED) 531 | if currTime == "09:16": 532 | # Trigger for Opening price Update 533 | try: 534 | # Update Opening price 535 | updateTodaysOpenPrice(stockList, currTime) 536 | try: 537 | # Execute R script only if it could update price in DB 538 | executeRscriptTradeSignal(currTime) 539 | except: 540 | print("Error: ERROR: in executeRscriptTradeSignal, But Continuing", file=sys.stderr) 541 | except: 542 | #exception, but continue again 543 | print("Error: ERROR: in updateTodaysOpenPrice, But Continuing", file=sys.stderr) 544 | elif currTime in periodicTimeList: 545 | # Trigger for Periodic price Update 546 | try: 547 | # Update periodic price 548 | updateTodaysPeriodicPrice(stockList, currTime) 549 | try: 550 | # Execute R script only if it could update price in DB 551 | executeRscriptTradeSignal(currTime) 552 | except: 553 | print("Error: ERROR: in executeRscriptTradeSignal, But Continuing", file=sys.stderr) 554 | except: 555 | #exception, but continue again 556 | print("Error: ERROR: in updateTodaysPeriodicPrice, But Continuing", file=sys.stderr) 557 | elif currTime == "15:20": 558 | # Close the RServe Conn 559 | global RconnStatus 560 | if RconnStatus == True: 561 | closeRServeConn() 562 | print("Rserve Conn closed", file=sys.stderr) 563 | # Thread Sleep 564 | sleep(1) 565 | 566 | ''' 567 | main function 568 | ''' 569 | if __name__ == '__main__': 570 | print("START: Entering Main", file=sys.stderr) 571 | # Get Stocks for VWAP 5 min 572 | stockList = getStocksForVWAP('ALLDAYS', vwap_strategy_time_tb_name) 573 | stockList = [stock['Stock'] for stock in stockList] 574 | if len(stockList) != 0: 575 | # Prepare the dictionary of time Updates 576 | for stock in stockList: 577 | # Periodic Google quote price update marker for each stock 578 | timeUpdateList = [] 579 | periodicPriceUpdateDict[stock] = timeUpdateList 580 | # Quote DB update marker for each stock 581 | currTimeQuoteDBUpdateList = [] 582 | currTimeQuoteDBUpdateMap[stock.upper()] = currTimeQuoteDBUpdateList 583 | # R execution update marker for each stock 584 | currTimeRExecList = [] 585 | currTimeRExecMap[stock] = currTimeRExecList 586 | # Update previous days data into VWAP temp DB 587 | prevDataUpdated = updatePreviousData(stockList) 588 | if prevDataUpdated == True: 589 | # Create RServe Conn 590 | createRServeConn() 591 | print("Rserve Conn created", file=sys.stderr) 592 | # start the thread of VWAP Functions 593 | thread = Thread(target = threadVWAPFunc, args = ()) 594 | thread.start() 595 | thread.join() 596 | print("Error: ERROR: Exiting Main", file=sys.stderr) 597 | # createRServeConn() # DEBUGGING 598 | # executeRscriptTradeSignal() # DEBUGGING 599 | # closeRServeConn() # DEBUGGING --------------------------------------------------------------------------------