Last active
July 11, 2018 16:12
-
-
Save theBrokeQuant/6756587 to your computer and use it in GitHub Desktop.
Live Environment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import live | |
import datetime | |
highlowPeriods = 10 | |
longMA = 200 | |
shortMA = 50 | |
portfolioFile = 'buyLow.txt' | |
comission = 3.95 | |
slippage = 0 | |
tickerList = live.importTickers('SP500.txt') | |
def buySignal(histData, liveQuote): | |
longMovingAve = live.sMA(histData, longMA) | |
shortMovingAve = live.sMA(histData, shortMA) | |
low = live.histLow(histData, highlowPeriods) | |
price = liveQuote['Price'] | |
if price > longMovingAve and price > shortMovingAve and price < low: | |
print '' | |
print 'Ticker:', liveQuote['Ticker'] | |
print 'Long MA:', longMovingAve | |
print 'Short MA:', shortMovingAve | |
print 'Low:', low | |
print 'Price:', price | |
print '' | |
return True | |
else: | |
return False | |
def sellSignal(histData, liveQuote, portDict): | |
shortMovingAverage = live.sMA(histData, shortMA) | |
high = live.histHigh(histData, highlowPeriods) | |
# if price sets new high or crosses MA | |
if (liveQuote['Price']<shortMovingAverage) or (liveQuote['Price'] > high): | |
return True | |
#if we run out of days | |
buyDate = portDict['Open Trades'][liveQuote['Ticker']]['Buy Date'] | |
buyDate = datetime.date(int(buyDate[0:4]), int(buyDate[5:7]), int(buyDate[8:10])) | |
if (datetime.date.today() - buyDate >= datetime.timedelta(14)) and (datetime.datetime.now().time() > datetime.time(14, 30, 0, 0)): | |
return True | |
return False | |
def quoteDict(quote): | |
quote = quote.split('\t') | |
qDict = {'Time': quote[0], | |
'Ticker': quote[1], | |
'Price': float(quote[2]), | |
'Volume': int(quote[3][:len(quote[3])-1]) | |
} | |
return qDict | |
def main(quote, portDict, histDataDict): | |
quote = quoteDict(quote) | |
#check if ticker has enough hitorical data | |
ticker = quote['Ticker'] | |
try: | |
histDataDict[ticker] | |
TickerData = True | |
except KeyError: | |
TickerData = False | |
if TickerData: | |
#if we're holding the security | |
if ticker in portDict['Open Trades']: | |
#update position market value | |
portDict = live.updateMarketValues(portDict, quote, 'Portfolios\\' + portfolioFile) | |
#sell if signal is triggered | |
if sellSignal(histDataDict[ticker], quote, portDict): | |
portDict = live.sell(quote, portDict, comission, slippage) | |
live.updatePortfolio(portDict, 'Portfolios\\' + portfolioFile) | |
#if we're not holding | |
if not(ticker in portDict['Open Trades']) and portDict['Avail Trades']: | |
#if the buy signal is triggered | |
if buySignal(histDataDict[ticker], quote): | |
#buy security | |
portDict = live.buy(quote, portDict, comission, slippage) | |
live.updatePortfolio(portDict, 'Portfolios\\' + portfolioFile) | |
return portDict |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Max Positions: 3.0 | |
Open Positions: 3.0 | |
Cost Basis: 9723.81 | |
Market Value: 9771.40 | |
Buying Power: 75.68 | |
Portfolio Value: 99847.08 | |
Return: | |
Open Trades: | |
BSX 2013-09-23 11.42 284 3243.28 3271.68 28.4 | |
STZ 2013-09-23 57.03 57 3250.71 3247.86 -2.85 | |
MUR 2013-09-23 60.94 53 3229.82 3247.31 17.49 | |
Closed Trades: | |
SEE 2013-09-20 28.87 113.0 2013-09-20 28.75 -13.56 | |
CI 2013-09-19 79.94 41.0 2013-09-19 78.63 -53.71 | |
UNH 2013-09-19 72.25 45.0 2013-09-19 71.93 -14.4 | |
LNC 2013-09-19 42.75 77.0 2013-09-19 42.67 -6.16 | |
AAPL 2013-09-11 469.68 7.0 2013-09-16 459.54 -70.98 | |
COG 2013-09-10 38.02 89.0 2013-09-13 37.55 -41.83 | |
SYMC 2013-09-04 25.25 134.0 2013-09-12 24.38 -116.58 | |
TSN 2013-08-26 30.85 116.0 2013-09-09 29.89 -111.36 | |
FOSL 2013-09-05 112.9 29.0 2013-09-06 112.68 -6.38 | |
FDO 2013-09-04 69.47 49.0 2013-09-04 68.43 -50.96 | |
DD 2013-08-20 57.46 59.0 2013-09-03 56.27 -70.21 | |
ACT 2013-08-28 130.77 25.0 2013-09-03 137.08 157.75 | |
LLTC 2013-08-21 38.58 87.0 2013-08-27 38.26 -27.84 | |
CCL 2013-08-09 36.69 96.0 2013-08-23 37.28 56.64 | |
USB 2013-08-15 36.88 91.0 2013-08-20 36.63 -22.75 | |
RF 2013-08-12 9.85 350.0 2013-08-19 9.76 -31.5 | |
GPC 2013-08-13 81.35 41.0 2013-08-14 80.65 -28.7 | |
ADP 2013-08-01 70.27 47.0 2013-08-12 72.79 118.44 | |
GPS 2013-08-09 44.43 80.0 2013-08-09 43.15 -102.4 | |
CVX 2013-08-02 124.75 29.0 2013-08-08 122.1 -76.85 | |
AMAT 2013-08-08 15.87 227.0 2013-08-08 15.65 -49.94 | |
BDX 2013-08-05 101.05 36.0 2013-08-07 100.06 -35.64 | |
ETN 2013-08-02 66.36 55.0 2013-08-02 66.01 -19.25 | |
DLPH 2013-07-31 53.91 65.0 2013-08-01 55.88 128.05 | |
DLTR 2013-07-26 52.44 67.0 2013-08-01 54.3 124.62 | |
VNO 2013-07-31 85.69 40.0 2013-07-31 83.73 -78.4 | |
NRG 2013-07-24 27.57 128.0 2013-07-30 27.01 -71.68 | |
NDAQ 2013-07-24 32.84 107.0 2013-07-30 32.29 -58.85 | |
SYY 2013-07-25 34.43 103.0 2013-07-25 34.32 -11.33 | |
BA 2013-07-12 100.7 33.0 2013-07-24 108.9 270.6 | |
MU 2013-07-09 13.14 253.0 2013-07-23 13.69 139.15 | |
SCHW 2013-07-16 20.98 159.0 2013-07-23 22.45 233.73 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#theBrokeQuant | |
#Last Modified: 6/08/2013 | |
import os | |
import urllib | |
import sys | |
import datetime | |
StartDay = 1 | |
StartMonth = 'January' | |
StartYear = 2005 | |
EndDay = 24 | |
EndMonth = 'September' | |
EndYear = 2013 | |
TimeInterval = "Day" | |
adjustPrices = True | |
fromFile = True | |
fileName = 'SP500.txt' | |
isUsersTickers = False | |
usersTickerList = ['ABT'] | |
def importData(StartDay, StartMonth, StartYear, EndDay, EndMonth, EndYear, Ticker, TimeInterval): | |
#Obtaining index value for months | |
OutputList = [] | |
Months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] | |
beginmonth = 0 | |
endmonth = 0 | |
for i in range (0,12): | |
if Months[i] == StartMonth: | |
beginmonth = i | |
if Months[i] == EndMonth: | |
endmonth = i | |
#first list element is the beginmonth index, second is endmonth | |
OutputList.append(beginmonth) | |
OutputList.append(endmonth) | |
#construct the URL | |
URL = "http://ichart.finance.yahoo.com/table.csv?s=" + Ticker + "&a=" + str(OutputList[0]) + "&b=" + str(StartDay) + "&c=" + str(StartYear) + "&d=" + str(OutputList[1]) + "&e=" + str(EndDay) + "&f=" + str(EndYear)+ "&g=" + TimeInterval[0] + "&ignore=.txt" | |
f = urllib.urlopen(URL) | |
#save to a temp file | |
file("temp.txt", "w").write(f.read()) | |
#import temp contents into list L | |
L = [] | |
File = open('temp.txt','rt') | |
FileList = File.readlines() | |
for filerow in range (0, len(FileList)): | |
L.append(str(FileList[filerow]).split(",")) | |
File.close() | |
#delete temp file | |
os.remove('temp.txt') | |
return L | |
#write the list to a tab seperated file | |
def listToTabSeperatedFile(L, filename): | |
f = open(filename, "w+") | |
for entry in L: | |
string = "" | |
i = 0 | |
while i < len(entry): | |
if i == 0: | |
string = string + str(entry[i]) | |
else: | |
string = string +" " + str(entry[i]) | |
i = i + 1 | |
if string[0] == 'D': | |
f.write(string) | |
else: | |
f.write(string + '\n') | |
f.close() | |
def main(): | |
tickerList = [] | |
if fromFile: | |
#open SP500 list and import tickers | |
f= open(fileName,"r") | |
lines = f.readline() | |
while lines: | |
tickerList.append((lines.split('\n'))[0]) | |
lines = f.readline() | |
f.close() | |
if isUsersTickers: | |
tickerList = usersTickerList | |
for Ticker in tickerList: | |
try: | |
#import the data for the ticker | |
L = importData(StartDay, StartMonth, StartYear, EndDay, EndMonth, EndYear, Ticker, TimeInterval) | |
#if we're adjusting prices | |
if adjustPrices: | |
newL = [] | |
for entry in L: | |
if entry[0][0] != 'D': | |
adjClose = float((entry[6].split("/n"))[0]) | |
#open = nonadjOpen/nonadjustClose * adjClose | |
adjOpen = str(round((float(entry[1])/float(entry[4]))*adjClose,2)) | |
#high = nonadjHigh/nonadjustClose * adjClose | |
adjHigh = str(round((float(entry[2])/float(entry[4]))*adjClose,2)) | |
#low = nonadjLow/nonadjustClose * adjClose | |
adjLow = str(round((float(entry[3])/float(entry[4]))*adjClose,2)) | |
tempL = [entry[0], adjOpen, adjHigh, adjLow, adjClose, entry[5], adjClose] | |
newL.append(tempL) | |
else: | |
newL.append(entry) | |
L = newL | |
#save data to file Ticker.txt in the folder Tickers asa tab seperated file | |
filename = "Daily\\" + Ticker + ".txt" | |
listToTabSeperatedFile(L, filename) | |
print Ticker | |
except: | |
print "Unknown error, skipped", Ticker | |
return True | |
main() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import os | |
import random | |
import datetime | |
import time | |
##import tradeLive | |
#Returns a simple moving average | |
def sMA(historicalData, periods): | |
numerator = 0 | |
for entry in historicalData[:periods]: | |
numerator = numerator + entry['Close'] | |
return numerator/periods | |
#Returns the historical low | |
def histLow(historicalData, periods): | |
low = sys.maxint | |
for entry in historicalData[:periods]: | |
if entry['Low'] < low: | |
low = entry['Low'] | |
return low | |
#Returns the historical high | |
def histHigh(historicalData, periods): | |
high = 0 | |
for entry in historicalData[:periods]: | |
if entry['High'] > high: | |
high = entry['High'] | |
return high | |
def retrieveFromFile(filename): | |
dataFeed = [] | |
f = open(filename,'r') | |
line = f.readline() | |
while line: | |
line = line.split('\t') | |
lineDict = {} | |
## print line | |
Ticker = line[1] | |
lineDict.update({'Ticker': Ticker}) | |
Price = float(line[2]) | |
lineDict.update({'Price': Price}) | |
Volume = int(line[3][:len(line[3])]) | |
lineDict.update({'Volume': Volume}) | |
Time = line[0] | |
Time = Time[:len(Time)-1] | |
lineDict.update({'Time': Time}) | |
dataFeed.append(lineDict) | |
line = f.readline() | |
f.close() | |
return dataFeed | |
def importData(ticker, beginDate, endDate, trailingPeriods): | |
beginDayFound = False | |
endDayFound = False | |
dataList = [] | |
#create data file path | |
workingDirectory = str(os.getcwd()) | |
dataDirectory = '' | |
for i in range(0, len(workingDirectory) - 4): | |
if workingDirectory[i:i+4] != 'Home': | |
dataDirectory = dataDirectory + workingDirectory[i] | |
else: | |
dataDirectory = dataDirectory + workingDirectory[i:i+4] + '\\Data\\Daily\\' | |
break | |
f = open(dataDirectory + ticker + ".txt", "r") | |
#Skip header line | |
line = f.readline().split() | |
line = f.readline().split() | |
while line: | |
#Start collecting on beginDate | |
if int(line[0][:4]+line[0][5:7]+line[0][8:11]) <= int(beginDate[:4]+beginDate[5:7]+beginDate[8:11]): | |
beginDayFound = True | |
#If end date found collect trailing period data | |
if int(line[0][:4]+line[0][5:7]+line[0][8:11]) < int(endDate[:4]+endDate[5:7]+endDate[8:11]): | |
endDayFound = True | |
i = 0 | |
while i < trailingPeriods: | |
#If there is not enough data to support trailing periods return nothing | |
try: | |
tempDict= {} | |
tempDict.update({'Date':line[0]}) | |
tempDict.update({'Open':float(line[1])}) | |
tempDict.update({'High':float(line[2])}) | |
tempDict.update({'Low':float(line[3])}) | |
tempDict.update({'Close':float(line[4])}) | |
tempDict.update({'Volume':float(line[5])}) | |
tempDict.update({'AdjClose':float(line[6])}) | |
dataList.append(tempDict) | |
except IndexError: | |
endDayFound = False | |
line = f.readline().split() | |
i = i + 1 | |
break | |
#If end date found and begin date not found collect data | |
else: | |
tempDict= {} | |
tempDict.update({'Date':line[0]}) | |
tempDict.update({'Open':float(line[1])}) | |
tempDict.update({'High':float(line[2])}) | |
tempDict.update({'Low':float(line[3])}) | |
tempDict.update({'Close':float(line[4])}) | |
tempDict.update({'Volume':float(line[5])}) | |
tempDict.update({'AdjClose':float(line[6])}) | |
dataList.append(tempDict) | |
line = f.readline().split() | |
if beginDayFound and endDayFound: | |
return dataList | |
else: | |
return [] | |
def importTickers(filename): | |
#import tickers from file | |
tickerList = [] | |
f = open(filename, 'r') | |
line = f.readline() | |
while line: | |
if line[len(line)-1] == '\n': | |
tickerList.append(line[:len(line)-1]) | |
else: | |
tickerList.append(line) | |
line = f.readline() | |
f.close() | |
## if tickerList: | |
## tickerList = random.shuffle(tickerList) | |
return tickerList | |
def stringToFloat(string): | |
newString = '' | |
for char in string: | |
if (char >= '0' and char <='9') or (char == '.'): | |
newString = newString + char | |
return float(newString) | |
def importPortfolio(portfolioFile): | |
portfolioDict = {} | |
f = open('Portfolios\\' + portfolioFile, 'r') | |
line = f.readline() | |
while line: | |
line = line.split(':') | |
#collect Max Positions | |
if line[0] == 'Max Positions' and line[1] == '\n': | |
portfolioDict.update({'Max Positions': 0}) | |
elif line[0] == 'Max Positions': | |
portfolioDict.update({'Max Positions': stringToFloat(line[1][:len(line[1])-1])}) | |
#collect Open Positions | |
if line[0] == 'Open Positions' and line[1] == '\n': | |
portfolioDict.update({'Open Positions': 0}) | |
elif line[0] == 'Open Positions': | |
portfolioDict.update({'Open Positions': stringToFloat(line[1][:len(line[1])-1])}) | |
#collect Cost Basis | |
if line[0] == 'Cost Basis' and line[1] == '\n': | |
portfolioDict.update({'Cost Basis': 0}) | |
elif line[0] == 'Cost Basis': | |
portfolioDict.update({'Cost Basis': stringToFloat(line[1][:len(line[1])-1])}) | |
#collect Market Value | |
if line[0] == 'Market Value' and line[1] == '\n': | |
portfolioDict.update({'Market Value':0}) | |
elif line[0] == 'Market Value': | |
portfolioDict.update({'Market Value':stringToFloat(line[1][:len(line[1])-1])}) | |
#collect Buying Power | |
if line[0] == 'Buying Power' and line[1] == '\n': | |
portfolioDict.update({'Buying Power':0}) | |
elif line[0] == 'Buying Power': | |
portfolioDict.update({'Buying Power': stringToFloat(line[1][:len(line[1])-1])}) | |
#collect Portfolio Value | |
if line[0] == 'Portfolio Value' and line[1] == '\n': | |
portfolioDict.update({'Portfolio Value':0}) | |
elif line[0] == 'Portfolio Value': | |
portfolioDict.update({'Portfolio Value':stringToFloat(line[1][:len(line[1])-1])}) | |
#collect Open Trades and place in dict | |
if line[0] == 'Open Trades': | |
openTradesDict = {} | |
line = f.readline() | |
line = f.readline() | |
while len(line) > 1: | |
line = line.split('\t') | |
tempDict = { | |
'Ticker': line[0], | |
'Buy Date': line[1], | |
'Buy Price': float(line[2]), | |
'Shares': int(line[3]), | |
'Cost Basis': float(line[4]), | |
'Market Value': float(line[5]), | |
'Net Gain': float(line[6][:len(line[6])-1]) | |
} | |
openTradesDict.update({line[0]: tempDict}) | |
line = f.readline() | |
portfolioDict.update({'Open Trades': openTradesDict}) | |
#collect Closed Trades and place in dict | |
if line[0] == 'Closed Trades': | |
closedTradesList = [] | |
line = f.readline() | |
line = f.readline() | |
while len(line) > 1: | |
line = line.split('\t') | |
tempDict = { | |
'Ticker': line[0], | |
'Buy Date': line[1], | |
'Buy Price': float(line[2]), | |
'Shares': float(line[3]), | |
'Sell Date': line[4], | |
'Sell Price': float(line[5]), | |
'Net Gain': float(line[6][:len(line[6])-1]) | |
} | |
closedTradesList.append(tempDict) | |
line = f.readline() | |
portfolioDict.update({'Closed Trades': closedTradesList}) | |
line = f.readline() | |
#Available trades | |
availTrades = portfolioDict['Max Positions'] - portfolioDict['Open Positions'] | |
portfolioDict.update({'Avail Trades': availTrades}) | |
#Trade Buffer | |
portfolioDict.update({'Trade Buffer':0}) | |
f.close() | |
return portfolioDict | |
def buy(quote, portfolioDict, comission, slippage): | |
#how much money per available trade | |
moneyAvail = portfolioDict['Buying Power'] / (portfolioDict['Avail Trades'] + portfolioDict['Trade Buffer']) | |
#price adjusted for slippage | |
slipPrice = quote['Price'] | |
#number of shares able to purchase | |
shareQuant = int(moneyAvail / slipPrice) | |
costBasis = shareQuant * slipPrice | |
#take out comission | |
buyingPower = portfolioDict['Buying Power'] - comission | |
#take out cost basis | |
buyingPower = buyingPower - costBasis | |
#newmarket value | |
marketValue = costBasis + portfolioDict['Market Value'] | |
#new cost basis | |
costBasis = costBasis + portfolioDict['Cost Basis'] | |
#new portfolio value | |
portfolioValue = marketValue + buyingPower | |
#update Open Trades | |
dictionary = portfolioDict['Open Trades'] | |
dictionary.update( | |
{quote['Ticker']: | |
{ | |
'Ticker': quote['Ticker'], | |
'Buy Date': str(datetime.date.today()), | |
'Buy Price': slipPrice, | |
'Shares': shareQuant, | |
'Cost Basis': shareQuant * slipPrice, | |
'Market Value': shareQuant * slipPrice, | |
'Net Gain': 0 | |
} | |
} | |
) | |
portfolioDict.update({'Open Trades':dictionary}) | |
portfolioDict.update({'Cost Basis': costBasis}) | |
portfolioDict.update({'Portfolio Value': portfolioValue}) | |
portfolioDict.update({'Buying Power': buyingPower}) | |
portfolioDict.update({'Market Value': marketValue}) | |
availPos = portfolioDict['Avail Trades'] - 1 | |
portfolioDict.update({'Avail Trades': availPos}) | |
openPositions = portfolioDict['Open Positions'] + 1 | |
portfolioDict.update({'Open Positions': openPositions}) | |
return portfolioDict | |
def sell(quote, portfolioDict, comission, slippage): | |
Ticker = quote['Ticker'] | |
tradesDict = portfolioDict['Open Trades'] | |
openTrade = tradesDict[Ticker] | |
#trade info | |
buyDate = openTrade['Buy Date'] | |
buyPrice = openTrade['Buy Price'] | |
shares = openTrade['Shares'] | |
sellDate = str(datetime.date.today()) | |
sellPrice = quote['Price'] | |
netGain = (sellPrice - buyPrice) * shares | |
tradeDict = { | |
'Ticker': Ticker, | |
'Buy Date': buyDate, | |
'Buy Price': buyPrice, | |
'Shares': shares, | |
'Sell Date': sellDate, | |
'Sell Price': sellPrice, | |
'Net Gain': netGain | |
} | |
#portfolio info | |
openPositions = portfolioDict['Open Positions'] - 1 | |
portfolioDict.update({'Open Positions': openPositions}) | |
costBasis = portfolioDict['Cost Basis'] - (buyPrice * shares) | |
portfolioDict.update({'Cost Basis': costBasis}) | |
marketValue = portfolioDict['Market Value'] - openTrade['Market Value'] | |
portfolioDict.update({'Market Value': marketValue}) | |
buyingPower = portfolioDict['Buying Power'] + openTrade['Market Value'] - comission | |
portfolioDict.update({'Buying Power': buyingPower}) | |
portfolioValue = marketValue + buyingPower | |
portfolioDict.update({'Portfolio Value': portfolioValue}) | |
closedTrades = portfolioDict['Closed Trades'] | |
closedTrades = [tradeDict] + closedTrades | |
portfolioDict.update({'Closed Trades': closedTrades}) | |
del tradesDict[Ticker] | |
portfolioDict.update({'Open Trades': tradesDict}) | |
tradeBuffer = portfolioDict['Trade Buffer'] + 1 | |
portfolioDict.update({'Trade Buffer': tradeBuffer}) | |
return portfolioDict | |
def updatePortfolio(portfolioDict, filename): | |
f = open(filename, 'w') | |
f.write('Max Positions:' + ' ' + str(portfolioDict['Max Positions']) + '\n') | |
f.write('Open Positions:' + ' ' + str(portfolioDict['Open Positions']) + '\n') | |
f.write('\n') | |
f.write('Cost Basis:' + ' ' + str(portfolioDict['Cost Basis']) + '\n') | |
f.write('Market Value:' + ' ' + str(portfolioDict['Market Value']) + '\n') | |
f.write('Buying Power:' + ' ' + str(portfolioDict['Buying Power']) + '\n') | |
f.write('\n') | |
f.write('Portfolio Value:' + ' ' + str(portfolioDict['Portfolio Value']) + '\n') | |
f.write('Return:\n') | |
f.write('\n') | |
f.write('Open Trades:\n') | |
f.write('\n') | |
for key in portfolioDict['Open Trades']: | |
subdict = portfolioDict['Open Trades'][key] | |
f.write(subdict['Ticker']+ '\t' + subdict['Buy Date'] + '\t' + str(subdict['Buy Price']) + '\t' + str(subdict['Shares']) + '\t'+ str(subdict['Cost Basis']) + '\t' + str(subdict['Market Value']) + '\t' + str(subdict['Net Gain']) + '\n') | |
f.write('\n') | |
f.write('Closed Trades:\n') | |
f.write('\n') | |
for trade in portfolioDict['Closed Trades']: | |
f.write(trade['Ticker'] + '\t' + trade['Buy Date']+ '\t' + str(trade['Buy Price'])+ '\t' + str(trade['Shares'])+ '\t' + str(trade['Sell Date'])+ '\t' + str(trade['Sell Price'])+ '\t' + str(trade['Net Gain'])+ '\n') | |
## | |
## | |
## f.write('') | |
f.close() | |
return False | |
#import historical data and store in dictionary with key ticker and value histdata | |
def histData(tickerList, beginDate, endDate, trailingPeriods): | |
tickerDict = {} | |
for ticker in tickerList: | |
tickerData = importData(ticker, beginDate, endDate, trailingPeriods) | |
if tickerData: | |
tickerDict.update({ticker:tickerData}) | |
else: | |
a = 0 | |
return tickerDict | |
def updateMarketValues(portfolioDict, quote, portfolioFile): | |
ticker = quote['Ticker'] | |
shares = portfolioDict['Open Trades'][ticker]['Shares'] | |
price = quote['Price'] | |
costBasis = portfolioDict['Open Trades'][ticker]['Cost Basis'] | |
marketValue = round(shares * price, 2) | |
netGain = round(marketValue - costBasis, 2) | |
portfolioMKT = portfolioDict['Market Value'] - portfolioDict['Open Trades'][ticker]['Net Gain'] | |
openTradeDict = portfolioDict['Open Trades'][ticker] | |
openTradeDict.update({'Market Value': marketValue, 'Net Gain': netGain}) | |
portfolioDict['Open Trades'].update({ticker:openTradeDict}) | |
portfolioMKT = portfolioMKT + netGain | |
portfolioDict.update({'Market Value'import sys | |
import live | |
import datetime | |
highlowPeriods = 10 | |
longMA = 200 | |
shortMA = 50 | |
portfolioFile = 'buyLow.txt' | |
comission = 3.95 | |
slippage = 0 | |
tickerList = live.importTickers('SP500.txt') | |
def buySignal(histData, liveQuote): | |
longMovingAve = live.sMA(histData, longMA) | |
shortMovingAve = live.sMA(histData, shortMA) | |
low = live.histLow(histData, highlowPeriods) | |
price = liveQuote['Price'] | |
if price > longMovingAve and price > shortMovingAve and price < low: | |
print '' | |
print 'Ticker:', liveQuote['Ticker'] | |
print 'Long MA:', longMovingAve | |
print 'Short MA:', shortMovingAve | |
print 'Low:', low | |
print 'Price:', price | |
print '' | |
return True | |
else: | |
return False | |
def sellSignal(histData, liveQuote, portDict): | |
shortMovingAverage = live.sMA(histData, shortMA) | |
high = live.histHigh(histData, highlowPeriods) | |
# if price sets new high or crosses MA | |
if (liveQuote['Price']<shortMovingAverage) or (liveQuote['Price'] > high): | |
return True | |
#if we run out of days | |
buyDate = portDict['Open Trades'][liveQuote['Ticker']]['Buy Date'] | |
buyDate = datetime.date(int(buyDate[0:4]), int(buyDate[5:7]), int(buyDate[8:10])) | |
if (datetime.date.today() - buyDate >= datetime.timedelta(14)) and (datetime.datetime.now().time() > datetime.time(14, 30, 0, 0)): | |
return True | |
return False | |
def quoteDict(quote): | |
quote = quote.split('\t') | |
qDict = {'Time': quote[0], | |
'Ticker': quote[1], | |
'Price': float(quote[2]), | |
'Volume': int(quote[3][:len(quote[3])-1]) | |
} | |
return qDict | |
def main(quote, portDict, histDataDict): | |
quote = quoteDict(quote) | |
#check if ticker has enough hitorical data | |
ticker = quote['Ticker'] | |
try: | |
histDataDict[ticker] | |
TickerData = True | |
except KeyError: | |
TickerData = False | |
if TickerData: | |
#if we're holding the security | |
if ticker in portDict['Open Trades']: | |
#update position market value | |
portDict = live.updateMarketValues(portDict, quote, 'Portfolios\\' + portfolioFile) | |
#sell if signal is triggered | |
if sellSignal(histDataDict[ticker], quote, portDict): | |
portDict = live.sell(quote, portDict, comission, slippage) | |
live.updatePortfolio(portDict, 'Portfolios\\' + portfolioFile) | |
#if we're not holding | |
if not(ticker in portDict['Open Trades']) and portDict['Avail Trades']: | |
#if the buy signal is triggered | |
if buySignal(histDataDict[ticker], quote): | |
#buy security | |
portDict = live.buy(quote, portDict, comission, slippage) | |
live.updatePortfolio(portDict, 'Portfolios\\' + portfolioFile) | |
return portDict | |
: portfolioMKT}) | |
portfolioValue = portfolioDict['Market Value'] + portfolioDict['Buying Power'] | |
portfolioDict.update({'Portfolio Value': portfolioValue}) | |
updatePortfolio(portfolioDict, portfolioFile) | |
return portfolioDict |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import httplib | |
import time | |
import datetime | |
import re | |
import random | |
import live | |
import buyLow | |
import buySMA | |
import buyLMA | |
import buyRand | |
import buyLow2 | |
import buyLow3 | |
runTime = 7.0 | |
marketOpen = 8.3 | |
marketClose = 15.00 | |
def initializePortfolios(): | |
portDict = { | |
'buyLow': live.importPortfolio('buyLow.txt'), | |
'buyLow2': live.importPortfolio('buyLow2.txt'), | |
'buyLow3': live.importPortfolio('buyLow3.txt'), | |
'buyLMA': live.importPortfolio('buyLMA.txt'), | |
'buySMA': live.importPortfolio('buySMA.txt'), | |
'buyRand': live.importPortfolio('buyRand.txt') | |
} | |
return portDict | |
def passQuote(quote, portDict, histDataDict): | |
print quote | |
buyLowPort = buyLow.main(quote, portDict['buyLow'], histDataDict) | |
portDict.update({'buyLow': buyLowPort}) | |
buyLow2Port = buyLow2.main(quote, portDict['buyLow2'], histDataDict) | |
portDict.update({'buyLow2': buyLow2Port}) | |
buyLow3Port = buyLow3.main(quote, portDict['buyLow3'], histDataDict) | |
portDict.update({'buyLow3': buyLow3Port}) | |
buyLMAPort = buyLMA.main(quote, portDict['buyLMA'], histDataDict) | |
portDict.update({'buyLMA': buyLMAPort}) | |
buySMAPort = buySMA.main(quote, portDict['buySMA'], histDataDict) | |
portDict.update({'buySMA': buySMAPort}) | |
buyRandPort = buyRand.main(quote, portDict['buyRand'], histDataDict) | |
portDict.update({'buyRand': buyRandPort}) | |
return portDict | |
#returns price and volume data as str(Price + '\t' + Volume ) | |
def parseHTMLSource(htmlSource, Ticker): | |
Price = None | |
Volume = None | |
sourceList = htmlSource.split('\n') | |
for line in sourceList: | |
#split line by common characters | |
line = re.split('\W+', line) | |
#loop through keywords in line | |
i = 0 | |
while i < len(line): | |
#price keyword found | |
if line[i] == 'time_rtq_ticker': | |
## print line[i:i+6] | |
#collect price | |
nonAlphChar = False | |
for char in Ticker: | |
if not((char >= 'A' and char <= 'Z') or (char >= 'a' and char <= 'z')): | |
nonAlphChar = True | |
if nonAlphChar: | |
Price = line[i+5] +'.' + line[i+6] | |
else: | |
Price = line[i+4] +'.' + line[i+5] | |
#volume keyword found | |
if line[i] == 'Volume' and line[i+3] == 'class': | |
Volume = '' | |
i = i + 1 | |
#start macro to collect volume data | |
beginVolume = True | |
while beginVolume: | |
if line[i] == 'span': | |
#begin collecting volume data | |
collect = True | |
i = i + 1 | |
while collect: | |
#end collection | |
if line[i] == 'span': | |
collect = False | |
beginVolume = False | |
break | |
#collect volume | |
if line[i][0] >= '0' and line[i][0] <= '9': | |
Volume = Volume + line[i] | |
i = i + 1 | |
else: | |
i = i + 1 | |
i = i + 1 | |
if Price and Volume: | |
return str((time.strftime('%X')) + '\t' + Ticker + '\t' + Price + '\t' + Volume) | |
else: | |
return False | |
def collectHTMLSource(Ticker): | |
conn.request('GET', '/q?s=' + Ticker) | |
r1 = conn.getresponse() | |
htmlSource = r1.read() | |
return htmlSource | |
def collectDataFromSource(htmlSource, Ticker): | |
#collect data, try 10 times upon error | |
htmlFound = False | |
for trys in range(0,10): | |
if parseHTMLSource(htmlSource, Ticker): | |
return parseHTMLSource(htmlSource, Ticker) | |
htmlFound = True | |
break | |
else: | |
htmlSource = collectHTMLSource(Ticker) | |
if not(htmlFound): | |
print Ticker | |
return False | |
while True: | |
firstRound = True | |
firstRound = True | |
#while the time is between runTime and marketClose. Start program | |
#if time is after market open | |
currentTime = float(str(time.strftime('%X'))[0:2] + str(time.strftime('%X'))[3:5])/100 | |
conn = httplib.HTTPConnection('finance.yahoo.com', timeout = 10) | |
while runTime < currentTime and currentTime < marketClose: | |
currentTime = float(str(time.strftime('%X'))[0:2] + str(time.strftime('%X'))[3:5])/100 | |
if marketOpen <= currentTime: | |
if firstRound: | |
beginDate = str(datetime.date.today()) | |
endDate = '2013-06-10' ##if you're reading this, this is bad naming but I promise it's correct. endDate is the 'from' and beginDate is the 'to.' | |
trailingPeriods = 300 | |
tickerList = live.importTickers('SP500.txt') | |
random.shuffle(tickerList) | |
histDataDict = live.histData(tickerList, beginDate, endDate, trailingPeriods) | |
#import portfolios | |
portDict = initializePortfolios() | |
#first thing to do | |
conn = httplib.HTTPConnection('finance.yahoo.com', timeout = 10) | |
firstRound = False | |
#select a Ticker | |
for Ticker in tickerList: | |
#establish connection and collect quote, retry if connection | |
#wasnt found | |
htmlSource = None | |
connEstablished = True | |
while connEstablished: | |
try: | |
htmlSource = collectHTMLSource(Ticker) | |
connEstablished = False | |
quote = collectDataFromSource(htmlSource, Ticker) | |
if quote: | |
#update portfolio | |
portDict = passQuote(quote, portDict, histDataDict) | |
break | |
except: | |
conn.close() | |
conn = httplib.HTTPConnection('finance.yahoo.com', timeout = 10) | |
if not(htmlSource): | |
print time.strftime('%X'), "Connection Error", Ticker | |
#close connection | |
conn.close() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sub collectDaily() | |
Dim worksheetname As String | |
Application.ScreenUpdating = False | |
Application.DisplayAlerts = False | |
For Each ws In Worksheets | |
ws.Activate | |
If Mid(ActiveSheet.Name, 1, 2) = "D." Then | |
ActiveSheet.Delete | |
End If | |
Next ws | |
For Each ticker In Sheets("Home").Cells.Range("K6:N8") | |
If ticker <> "" Then | |
For Each c In Sheets("Home").Cells.Range("K10,K12,K14,K16") | |
fromDateText = CStr(c.Offset(0, 1)) + "." + CStr(c.Offset(0, 2)) + "." + CStr(c.Offset(0, 3)) | |
toDateText = CStr(c.Offset(1, 1)) + "." + CStr(c.Offset(1, 2)) + "." + CStr(c.Offset(1, 3)) | |
fromDate = DateSerial(c.Offset(0, 1), c.Offset(0, 2), c.Offset(0, 3)) | |
toDate = DateSerial(c.Offset(1, 1), c.Offset(1, 2), c.Offset(1, 3)) | |
If c.Offset(0, 1) <> "" Then | |
'''IMPORT Ticker Data | |
'import to new sheet | |
ActiveWorkbook.Worksheets.Add | |
With ActiveSheet.QueryTables.Add(Connection:= _ | |
"TEXT;" + ActiveWorkbook.Path + "\Data\Daily\" + ticker + ".txt", _ | |
Destination:=Range("$A$1")) | |
.Name = "D. " + ticker | |
.FieldNames = True | |
.RowNumbers = False | |
.FillAdjacentFormulas = False | |
.PreserveFormatting = True | |
.RefreshOnFileOpen = False | |
.RefreshStyle = xlInsertDeleteCells | |
.SavePassword = False | |
.SaveData = True | |
.AdjustColumnWidth = True | |
.RefreshPeriod = 0 | |
.TextFilePromptOnRefresh = False | |
.TextFilePlatform = 437 | |
.TextFileStartRow = 1 | |
.TextFileParseType = xlDelimited | |
.TextFileTextQualifier = xlTextQualifierDoubleQuote | |
.TextFileConsecutiveDelimiter = True | |
.TextFileTabDelimiter = False | |
.TextFileSemicolonDelimiter = False | |
.TextFileCommaDelimiter = False | |
.TextFileSpaceDelimiter = True | |
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1) | |
.TextFileTrailingMinusNumbers = True | |
.Refresh BackgroundQuery:=False | |
End With | |
'fix adj close | |
Cells.Range("G1:G1").Value = "Adj Close" | |
Cells.Range("H1:H1").ClearContents | |
'rename sheet | |
worksheetname = "D. " + ticker + " " + fromDateText + "-" + toDateText | |
ActiveSheet.Name = worksheetname | |
'move to end | |
ActiveSheet.Move _ | |
After:=ActiveWorkbook.Sheets("Home") | |
beginCell = 0 | |
endCell = 0 | |
i = 0 | |
For Each d In ActiveSheet.Cells.Range("A:A") | |
If d <> "Date" Then | |
If d < toDate Then | |
If beginCell = 0 Then | |
beginCell = i | |
End If | |
End If | |
If d < fromDate Then | |
If endCell = 0 Then | |
endCell = i + 1 | |
Exit For | |
End If | |
End If | |
End If | |
i = i + 1 | |
Next d | |
If beginCell > 2 Then | |
ActiveSheet.Cells.Range("A2:G" + CStr(beginCell - 1)).Select | |
Selection.ClearContents | |
End If | |
If endCell > 2 Then | |
ActiveSheet.Cells.Range("A" + CStr(endCell) + ":G1000000").ClearContents | |
End If | |
Columns("A:G").Select | |
ActiveSheet.Sort.SortFields.Clear | |
ActiveSheet.Sort.SortFields.Add Key:=Range("A1:A1000000") _ | |
, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal | |
With ActiveSheet.Sort | |
.SetRange Range("A1:G1000000") | |
.Header = xlGuess | |
.MatchCase = False | |
.Orientation = xlTopToBottom | |
.SortMethod = xlPinYin | |
.Apply | |
End With | |
'Resize row 1 | |
Rows("1:1").RowHeight = 30 | |
' Adjust columns A:G | |
Columns("A:G").Select | |
Selection.ColumnWidth = 10 | |
Selection.HorizontalAlignment = xlCenter | |
Selection.VerticalAlignment = xlCenter | |
' Add price chart | |
ActiveSheet.Shapes.AddChart.Select | |
ActiveChart.ChartType = xlLine | |
ActiveChart.SetSourceData Source:=Range("='" + worksheetname + "'" + "!$G$2:$G$" + CStr(endCell - beginCell + 1)) | |
ActiveChart.Legend.Delete | |
ActiveChart.SeriesCollection(1).XValues = _ | |
"='" + worksheetname + "'!$A$2:$A$" + CStr(endCell - beginCell + 1) | |
ActiveChart.Axes(xlValue).TickLabels.NumberFormat = "$#,##0.00" | |
ActiveSheet.Shapes("Chart 1").Line.Visible = msoFalse | |
minValue = WorksheetFunction.Min(ActiveSheet.Range("G2:G" + CStr(endCell - beginCell + 1))) | |
maxValue = WorksheetFunction.Max(ActiveSheet.Range("G2:G" + CStr(endCell - beginCell + 1))) | |
ActiveChart.Axes(xlValue).MinimumScale = minValue * 0.98 | |
ActiveChart.Axes(xlValue).MaximumScale = maxValue * 1.02 | |
ActiveChart.ChartArea.Width = 590 | |
ActiveChart.ChartArea.Height = 175 | |
With ActiveSheet | |
.ChartObjects(1).Top = .Range("H2").Top | |
.ChartObjects(1).Left = .Range("H2").Left | |
.Shapes("Chart 1").IncrementLeft 3 | |
End With | |
' Add volume chart | |
ActiveSheet.Shapes.AddChart.Select | |
ActiveChart.ChartType = xlColumnClustered | |
ActiveChart.SetSourceData Source:=Range("='" + worksheetname + "'" + "!$F$2:$F$" + CStr(endCell - beginCell + 1)) | |
ActiveChart.Legend.Delete | |
ActiveChart.SeriesCollection(1).XValues = _ | |
"='" + worksheetname + "'!$A$2:$A$" + CStr(endCell - beginCell + 1) | |
ActiveChart.Axes(xlValue).TickLabels.NumberFormat = "0.E+00" | |
ActiveChart.ChartArea.Width = 590 | |
ActiveChart.ChartArea.Height = 160 | |
With ActiveSheet | |
.Shapes("Chart 2").Line.Visible = msoFalse | |
.ChartObjects(2).Top = .Range("H14").Top | |
.ChartObjects(2).Left = .Range("H14").Left | |
.Shapes("Chart 2").IncrementLeft 3 | |
End With | |
' Make background white | |
ActiveSheet.Cells.Select | |
With Selection.Interior | |
.Pattern = xlSolid | |
.PatternColorIndex = xlAutomatic | |
.ThemeColor = xlThemeColorDark1 | |
.TintAndShade = 0 | |
.PatternTintAndShade = 0 | |
End With | |
'Modify table body | |
Range("A1:G" + CStr(endCell - beginCell + 1)).Select | |
With Selection.Borders(xlEdgeLeft) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlEdgeTop) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlEdgeBottom) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlEdgeRight) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlInsideVertical) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = 0.399945066682943 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlInsideHorizontal) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = 0.599963377788629 | |
.Weight = xlThin | |
End With | |
With Selection.Interior | |
.Pattern = xlSolid | |
.PatternColorIndex = xlAutomatic | |
.ThemeColor = xlThemeColorAccent1 | |
.TintAndShade = 0.799981688894314 | |
.PatternTintAndShade = 0 | |
End With | |
ActiveWindow.SmallScroll Down:=-242 | |
Range("E12").Select | |
' Format header | |
Range("A1:G1").Select | |
With Selection | |
Selection.Font.Bold = True | |
Selection.Font.Size = 12 | |
End With | |
With Selection.Borders(xlEdgeLeft) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlEdgeTop) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlEdgeBottom) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlEdgeRight) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = -0.499984740745262 | |
.Weight = xlMedium | |
End With | |
With Selection.Borders(xlInsideVertical) | |
.LineStyle = xlContinuous | |
.ThemeColor = 5 | |
.TintAndShade = 0.399914548173467 | |
.Weight = xlMedium | |
End With | |
Selection.Borders(xlInsideHorizontal).LineStyle = xlNone | |
With Selection.Interior | |
.Pattern = xlSolid | |
.PatternColorIndex = xlAutomatic | |
.ThemeColor = xlThemeColorAccent1 | |
.TintAndShade = 0.399945066682943 | |
.PatternTintAndShade = 0 | |
End With | |
'Freeze top row | |
Rows("1:1").Select | |
With ActiveWindow | |
.SplitColumn = 0 | |
.SplitRow = 1 | |
End With | |
ActiveWindow.FreezePanes = True | |
' Format ticker date header | |
ActiveSheet.Cells.Range("I1:I1").Value = ticker + " " + CStr(c.Offset(0, 1)) + "/" + CStr(c.Offset(0, 2)) + "/" + CStr(c.Offset(0, 3)) + " - " + CStr(c.Offset(1, 1)) + "/" + CStr(c.Offset(1, 2)) + "/" + CStr(c.Offset(1, 3)) | |
Range("I1").Select | |
With Selection | |
.Font.Bold = True | |
.HorizontalAlignment = xlLeft | |
.VerticalAlignment = xlCenter | |
.Font.Size = 12 | |
End With | |
ActiveSheet.Cells.Range("A2:A2").Select | |
End If | |
Next c | |
End If | |
Next ticker | |
Sheets("Home").Activate | |
End Sub |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment