Commit f2f8a4eb by Lawrence

Add algo trading

parent e5242556
This source diff could not be displayed because it is too large. You can view the blob instead.
#!/usr/bin/env python3
import csv
import urllib.request
from io import StringIO
def get_date(string):
return string.split(" ")[0]
def get_time(string):
time_str = string.split(" ")[1]
arr = time_str.split(":")
arr = [int(o) for o in arr]
return arr
def main():
with urllib.request.urlopen("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=demo&datatype=csv") as f:
html = StringIO(f.read().decode('utf-8'))
reader = csv.DictReader(html, delimiter=",")
data_dict = {}
for line in reader:
date = get_date(line["timestamp"])
if not date in data_dict:
data_dict[date] = {}
time = get_time(line["timestamp"])
if time[0] == 9 and time[1] == 25:
data_dict[date]["premarket"] = line["open"]
if time[0] == 9 and time[1] == 35:
data_dict[date]["open"] = line["open"]
if time[0] == 9 and time[1] == 40:
data_dict[date]["after_open"] = line["open"]
print(data_dict)
if __name__ == "__main__":
main()
\ No newline at end of file
......@@ -3,6 +3,8 @@
import csv
import argparse
import os
import matplotlib.pyplot as plt
import numpy as np
STOCK_FILE_NAME = "historical_stock_prices.csv"
......@@ -15,9 +17,8 @@ def make_stock_file(stocks, stock):
def get_stocks(file_name, stock):
if os.path.isfile("stock/" + stock):
file_name = stock
if os.path.isfile("stocks/" + stock):
file_name = "stocks/" + stock
csvfile = open(file_name)
reader = csv.DictReader(csvfile)
......@@ -35,37 +36,64 @@ def get_stocks(file_name, stock):
return stocks
def average_gain_after_positive(stocks):
def get_data(stocks):
av_gain = 0
count = 0
x = []
y = []
for i in range(2, len(stocks)):
if float(stocks[i - 1]["open"]) - float(stocks[i - 2]["open"]) > 0:
av_gain += float(stocks[i]["open"]) - float(stocks[i - 1]["open"])
count += 1
return av_gain / count
def average_gain_after_turnaround(stocks):
av_gain = 0
count = 0
for i in range(3, len(stocks)):
if float(stocks[i - 1]["open"]) - float(stocks[i - 2]["open"]) > 0 and float(stocks[i - 2]["open"]) - float(stocks[i - 3]["open"]) < 0:
av_gain += float(stocks[i]["open"]) - float(stocks[i - 1]["open"])
count += 1
return av_gain / count
x.append(float(stocks[i - 1]["open"]) - float(stocks[i - 2]["open"]))
y.append(float(stocks[i]["open"]) - float(stocks[i - 1]["open"]))
return x, y
NUM_CATEGORIES = 15
def make_2d(x_list, y_list):
out = [[0] * NUM_CATEGORIES for i in range(NUM_CATEGORIES)]
for i in range(len(x_list)):
x = x_list[i]
y = y_list[i]
if x < MAX_VALUE and x > -MAX_VALUE and y < MAX_VALUE and y > -MAX_VALUE:
x_index = int((x - -MAX_VALUE) / INTERVAL)
y_index = int((y - -MAX_VALUE) / INTERVAL)
out[x_index][y_index] += 1
return out
def get_bins(x, y):
num_in_bins = [0] * NUM_CATEGORIES
value = [0] * NUM_CATEGORIES
for i in range(len(x)):
index = int((x[i] - -MAX_VALUE) / INTERVAL)
if 0 <= index < NUM_CATEGORIES:
num_in_bins[index] += 1
value[index] += y[i]
value = np.divide(value, num_in_bins)
return value
def main(stock):
stocks = get_stocks(STOCK_FILE_NAME, stock)
print("Average gain after a positive delta: %f" % average_gain_after_positive(stocks))
print("Average gain after a turnaround: %f" % average_gain_after_turnaround(stocks))
print("Average gain in total: %f" % ((float(stocks[len(stocks) - 1]["open"]) - float(stocks[0]["open"])) / (len(stocks) - 1)))
x, y = get_data(stocks)
std = np.std(x)
global MAX_VALUE
global INTERVAL
MAX_VALUE = 2 * std
INTERVAL = MAX_VALUE * 2 / NUM_CATEGORIES
vals = get_bins(x, y)
print("Standard deviation: %f" % std)
bins = [i * INTERVAL + -MAX_VALUE for i in range(NUM_CATEGORIES + 1)]
plt.hist(bins[:-1], bins, weights=vals)
plt.ylabel("Average gain on day n")
plt.xlabel("Gain on day n - 1")
plt.figure()
plt.hist(x, [i * INTERVAL + -MAX_VALUE for i in range(NUM_CATEGORIES + 1)])
plt.xlabel("Gain")
plt.ylabel("Density")
plt.show()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
......
......@@ -56,7 +56,5 @@ def main():
if count_pos_dict[i] > 0 and count_turn_dict[i] > 0 and count_dict[i] > 0:
writer.writerow([i, av_gain_pos_dict[i] / count_pos_dict[i], av_gain_turn_dict[i] / count_turn_dict[i], av_gain_dict[i] / count_dict[i]])
if __name__ == "__main__":
main()
#!/usr/bin/env python3
import csv
FILE_NAME = "all_stocks"
def main():
csvfile = open(FILE_NAME)
reader = csv.DictReader(csvfile)
count = 0
greater_count = 0
for i in reader:
if i["av_gain_positive"] > i["av_gain"]:
greater_count += 1
count += 1
print("Percent stocks for which average gain after a positive day is greater than average gain on any day: %f" % (greater_count / count))
if __name__ == "__main__":
main()
......@@ -9,6 +9,8 @@ import os.path
import random
from bst import Node, search, insert, inorder
import argparse
from correlation_test import make_stock_file
import numpy as np
ACTION_BUY = 1
ACTION_SELL = 2
......@@ -60,7 +62,7 @@ class StockSim:
i += 1
def make_stocks_list(self):
csvfile = open(self.file_name )
csvfile = open(self.file_name)
reader = csv.DictReader(csvfile)
tree = Node(reader.__next__()["ticker"])
......@@ -78,16 +80,23 @@ class StockSim:
f.write(i + "\n")
def get_stocks(self):
csvfile = open(self.file_name)
reader = csv.DictReader(csvfile)
self.stocks = []
if os.path.isfile("stocks/" + self.stock):
self.file_name = "stocks/" + self.stock
count = 0
for i in reader:
if(count >= DAYS_AFTER_INITIAL and i["ticker"] == self.stock and str_year_greater_eq_than(i["date"], self.year)):
self.stocks.append(i)
count += 1
with open(self.file_name) as csvfile:
reader = csv.DictReader(csvfile)
self.stocks = []
count = 0
for i in reader:
if(count >= DAYS_AFTER_INITIAL and i["ticker"] == self.stock and str_year_greater_eq_than(i["date"], self.year)):
self.stocks.append(i)
count += 1
if not os.path.isfile("stocks/" + self.stock):
make_stock_file(self.stocks, self.stock)
def get_buy_delta(self):
min_buy = float(self.stocks[self.current_index]["open"])
......@@ -125,6 +134,18 @@ class StockSim:
print("Stock change for time held: %f%%" % (percent_change * self.time_held / self.current_index))
print("Money made: %f%%" % (self.money_made / self.start_price * 100))
def buy(self):
if self.bought_index == -1:
self.bought_index = self.current_index
return True
return False
def sell(self):
if self.bought_index != -1:
self.money_made += float(self.stocks[self.current_index]["open"]) - float(self.stocks[self.bought_index]["open"])
self.time_held += self.current_index - self.bought_index
self.bought_index = -1
def buy_sell_thread(self):
print("Enter action (b for buy, s for sell, x to quit)")
......@@ -134,8 +155,7 @@ class StockSim:
action = str_to_act(input(""))
current_price = float(self.stocks[self.current_index]["open"])
if action == ACTION_BUY:
if self.bought_index == -1:
self.bought_index = self.current_index
if self.buy():
print("Bought stock for %f" % current_price)
if self.get_relative_buy_rating() > 0:
print("Good buy!!!!")
......@@ -144,10 +164,7 @@ class StockSim:
else:
print("Already have stock - can't buy")
elif action == ACTION_SELL:
if self.bought_index != -1:
self.money_made += current_price - float(self.stocks[self.bought_index]["open"])
self.time_held += self.current_index - self.bought_index
self.bought_index = -1
if(self.sell()):
print("Sold stock for %f" % current_price)
print("Money made: %f" % self.money_made)
if self.get_relative_sell_rating() > 0:
......@@ -163,7 +180,23 @@ class StockSim:
self.print_data()
i += 1
def run(self, stock="random", year=-1, file_name="historical_stock_prices.csv", plot_size=30):
def get_delta(self, days_before):
if self.current_index - days_before - 1 >= 0:
return float(self.stocks[self.current_index - days_before]["open"]) - float(self.stocks[self.current_index - days_before - 1]["open"])
return False
def previous_day_dist_algo(self):
if self.get_delta(0):
self.delta_list.append(self.get_delta(0))
mean = np.mean(self.delta_list)
std = np.std(self.delta_list)
if self.get_delta(0) > mean - std or self.get_delta(0) < mean + std:
self.buy()
if self.current_index > self.bought_index:
self.sell()
def run(self, stock="random", year=-1, file_name="historical_stock_prices.csv", plot_size=30, algo=True):
self.bought_index = -1
self.money_made = 0
......@@ -178,6 +211,8 @@ class StockSim:
self.file_name = file_name
self.stock = stock
self.current_index = 0
self.algo = algo
self.delta_list = []
if stock == "random":
self.stock = self.random_stock()
......@@ -185,27 +220,36 @@ class StockSim:
self.get_stocks()
self.start_price = float(self.stocks[0]["open"])
thread = threading.Thread(target=self.buy_sell_thread)
thread.start()
if not self.algo:
thread = threading.Thread(target=self.buy_sell_thread)
thread.start()
plt.ion()
for i in range(len(self.stocks)):
self.current_index = i
x = []
y = []
start_loc = max(0, i - plot_size)
for j in range(start_loc, i):
x.append(self.stocks[j]["date"])
y.append(float(self.stocks[j]["open"]))
plot(x, y, self.stock)
plt.pause(1)
if not self.algo:
x = []
y = []
start_loc = max(0, i - plot_size)
for j in range(start_loc, i):
x.append(self.stocks[j]["date"])
y.append(float(self.stocks[j]["open"]))
plot(x, y, self.stock)
plt.pause(1)
else:
self.previous_day_dist_algo()
if self.algo:
self.print_data()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--stock", default="random")
parser.add_argument("--year", default="-1")
parser.add_argument("-stock", default="random")
parser.add_argument("-year", default="-1")
parser.add_argument("-algo", action='store_true')
args = parser.parse_args()
sim = StockSim()
sim.run(stock=args.stock, year=str_to_year(args.year))
sim.run(stock=args.stock, year=str_to_year(args.year), algo=args.algo)
from selenium import webdriver
from datetime import date
import time
def main(stock):
file = open(stock, "a")
prev_minute = -1
while True:
now = datetime.now()
if now.time().minute - prev_minute >= 1 or (prev_minute == 59 and now.time().minute != 59):
dt_string = now.strftime("%d/%m/%Y %H:%M")
file.write(dt_string + " " + )
prev_minute = now.time().minute
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--stock", default="GOOGL")
args = parser.parse_args()
main(stock)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment