Implement marketsim without commission and impact
This commit is contained in:
@@ -29,9 +29,11 @@ import pandas as pd
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from util import get_data, plot_data
|
from util import get_data, plot_data
|
||||||
from optimize_something.optimization import calculate_stats
|
from optimize_something.optimization import calculate_stats
|
||||||
|
|
||||||
|
|
||||||
def read_orders(orders_file):
|
def read_orders(orders_file):
|
||||||
"""
|
"""
|
||||||
Parser orders into the form:
|
Parser orders into the form:
|
||||||
@@ -48,35 +50,78 @@ def read_orders(orders_file):
|
|||||||
2011-01-10,AAPL,SELL,1500
|
2011-01-10,AAPL,SELL,1500
|
||||||
"""
|
"""
|
||||||
orders = pd.read_csv(orders_file,
|
orders = pd.read_csv(orders_file,
|
||||||
|
index_col=['Date'],
|
||||||
dtype='|str, str, str, i4',
|
dtype='|str, str, str, i4',
|
||||||
parse_dates=["Date"])
|
parse_dates=['Date'])
|
||||||
orders.sort_values(by="Date", inplace=True)
|
orders.sort_values(by="Date", inplace=True)
|
||||||
return orders
|
return orders
|
||||||
|
|
||||||
|
|
||||||
def get_order_book_info(orders):
|
def get_order_book_info(orders):
|
||||||
"""Return start_date, end_date, and symbols (as a list)."""
|
"""Return start_date, end_date, and symbols (as a list)."""
|
||||||
start_date = orders.iloc[0].Date
|
start_date = orders.index[0]
|
||||||
end_date = orders.iloc[0].Date
|
end_date = orders.index[-1]
|
||||||
symbols = sorted(list((set(orders.Symbol.tolist()))))
|
symbols = sorted(list((set(orders.Symbol.tolist()))))
|
||||||
return start_date, end_date, symbols
|
return start_date, end_date, symbols
|
||||||
|
|
||||||
|
|
||||||
|
def get_portfolio_value(holding, prices):
|
||||||
|
"""Calculate the current portofolio value."""
|
||||||
|
value = 0
|
||||||
|
for ticker, shares in holding.items():
|
||||||
|
if ticker == 'cash':
|
||||||
|
value += shares
|
||||||
|
else:
|
||||||
|
value += shares * prices[ticker]
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def handle_orders(orders, holding, adj_closing_prices):
|
||||||
|
"""Process the orders."""
|
||||||
|
for date, order in orders.iterrows():
|
||||||
|
symbol, order, shares = order
|
||||||
|
adj_closing_price = adj_closing_prices[symbol]
|
||||||
|
cost = shares * adj_closing_price
|
||||||
|
if order == "BUY":
|
||||||
|
# print(f"Buy {shares:6} of {symbol:4} on {date}")
|
||||||
|
holding['cash'] -= cost
|
||||||
|
holding[symbol] += shares
|
||||||
|
elif order == "SELL":
|
||||||
|
# print(f"Sell {shares:6} of {symbol:4} on {date}")
|
||||||
|
holding['cash'] += cost
|
||||||
|
holding[symbol] -= shares
|
||||||
|
else:
|
||||||
|
raise Exception("Unexpected order type.")
|
||||||
|
|
||||||
|
|
||||||
def compute_portvals(orders_file="./orders/orders-01.csv", start_val=1000000, commission=9.95, impact=0.005):
|
def compute_portvals(orders_file="./orders/orders-01.csv", start_val=1000000, commission=9.95, impact=0.005):
|
||||||
orders = read_orders(orders_file)
|
orders = read_orders(orders_file)
|
||||||
start_date, end_date, symbols = get_order_book_info(orders)
|
start_date, end_date, symbols = get_order_book_info(orders)
|
||||||
|
|
||||||
# In the template, instead of computing the value of the portfolio, we just
|
# Tickers in the orderbook over the date_range in the order book.
|
||||||
# read in the value of IBM over 6 months
|
prices = get_data(symbols, pd.date_range(start_date, end_date))
|
||||||
start_date = dt.datetime(2008, 1, 1)
|
prices['Portval'] = pd.Series(0.0, index=prices.index)
|
||||||
end_date = dt.datetime(2008, 6, 1)
|
|
||||||
portvals = get_data(['IBM'], pd.date_range(start_date, end_date))
|
|
||||||
portvals = portvals[['IBM']] # remove SPY
|
|
||||||
|
|
||||||
|
# A dictionary to keep track of the assets we are holding.
|
||||||
|
holding = {s: 0 for s in symbols}
|
||||||
|
holding['cash'] = start_val
|
||||||
|
|
||||||
|
orders_processed = 0
|
||||||
|
for date, values in prices.iterrows():
|
||||||
|
if date in orders.index:
|
||||||
|
current_orders = orders.loc[date:date]
|
||||||
|
orders_processed += current_orders.shape[0]
|
||||||
|
handle_orders(current_orders, holding, values)
|
||||||
|
|
||||||
|
# Compute portfolio value at the end of day.
|
||||||
|
values['Portval'] = get_portfolio_value(holding, values)
|
||||||
|
|
||||||
|
# Make sure we have processed all orders. If there was an order on a
|
||||||
|
# non-trading day we would currently not handle it.
|
||||||
|
assert(orders.shape[0] == orders_processed)
|
||||||
|
|
||||||
|
portvals = prices[['Portval']]
|
||||||
return portvals
|
return portvals
|
||||||
# Don't know why this was in template. Keep for now.
|
|
||||||
# rv = pd.DataFrame(index=portvals.index, data=portvals.values)
|
|
||||||
# return rv
|
|
||||||
|
|
||||||
|
|
||||||
def test_code():
|
def test_code():
|
||||||
@@ -89,14 +134,8 @@ def test_code():
|
|||||||
else:
|
else:
|
||||||
raise Exception("warning, code did not return a DataFrame")
|
raise Exception("warning, code did not return a DataFrame")
|
||||||
|
|
||||||
# One way of getting the portfolio dates
|
start_date = portvals.index[0]
|
||||||
# print(portvals.index[0])
|
end_date = portvals.index[-1]
|
||||||
|
|
||||||
# Get portfolio stats.
|
|
||||||
start_date = dt.datetime(2008, 1, 1)
|
|
||||||
end_date = dt.datetime(2008, 6, 1)
|
|
||||||
|
|
||||||
|
|
||||||
cum_ret, avg_daily_ret, \
|
cum_ret, avg_daily_ret, \
|
||||||
std_daily_ret, sharpe_ratio = calculate_stats(portvals.to_frame(), [1])
|
std_daily_ret, sharpe_ratio = calculate_stats(portvals.to_frame(), [1])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user