A financial strategy produces orders. These orders are transmitted to a broker. The broker checks the validity of the order and sends each valid order to the market and sends back a transaction. Every time we buy some shares the broker opens a position with the buy price. If we sell some shares this should be related to a position in order to calculate the profit. Therefore the position information is important mainly in order to calculate profit. We call a buy/sell matching a trade. The sum of all positions are called the portfolio.
Symbols are the financial instrument that we can invest in. At a given point, there is no known price but the price depends on the buyers' and sellers' bid prices. The price of a symbol is calculated by the market for a given order. Therefore the price of a symbol may change constantly. Usually symbols have candle data (5min, 1day) etc.. storing open, close, low and high values.
import pandas as pd
import pandas_datareader.data as web
from pandas.tseries.offsets import BDay
import datetime
import warnings
from copy import deepcopy
import numpy as np
%matplotlib inline
from scipy.stats import linregress
import matplotlib.pyplot as plt
from math import sqrt
import scipy.stats as st
/home/can/anaconda2/lib/python2.7/site-packages/pandas/computation/__init__.py:19: UserWarning: The installed version of numexpr 2.4.4 is not supported in pandas and will be not be used UserWarning)
symbols = ['AEFES.IS', 'AKENR.IS', 'AKSA.IS', 'AKBNK.IS', 'GARAN.IS',
'MGROS.IS', 'THYAO.IS', 'TRKCM.IS', 'ZOREN.IS', 'XU100.IS',
'ALARK.IS', 'CIMSA.IS', 'HALKB.IS', 'TKFEN.IS', 'FROTO.IS',
'DOAS.IS', 'KARSN.IS', 'TMSN.IS', 'YKBNK.IS', 'VAKBN.IS',
'ULKER.IS', 'TCELL.IS', 'SISE.IS', 'EREGL.IS', 'PETKM.IS',
'BJKAS.IS', 'AFYON.IS', 'KOZAL.IS', 'GOODY.IS', 'VAKFN.IS']
start = datetime.datetime(2015,1,1)
end = datetime.datetime.now()
prices = pd.DataFrame()
for symbol in symbols:
f = web.DataReader(symbol, 'yahoo', start, end)
f['symbol'] = symbol
prices = pd.concat([prices, f])
prices;
How do I calculae the adjusted closing price? http://www.investopedia.com/ask/answers/06/adjustedclosingprice.asp
prices = prices.pivot(columns="symbol", values="Adj Close")
prices.tail()
symbol | AEFES.IS | AFYON.IS | AKBNK.IS | AKENR.IS | AKSA.IS | ALARK.IS | BJKAS.IS | CIMSA.IS | DOAS.IS | EREGL.IS | ... | THYAO.IS | TKFEN.IS | TMSN.IS | TRKCM.IS | ULKER.IS | VAKBN.IS | VAKFN.IS | XU100.IS | YKBNK.IS | ZOREN.IS |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||||||||||
2016-09-26 | 18.70 | 5.69 | 7.96 | 0.94 | 8.20 | 3.44 | 4.58 | 14.92 | 9.93 | 4.28 | ... | 5.12 | 7.37 | 7.51 | 2.44 | 21.44 | 4.43 | 1.17 | 76725.7031 | 3.66 | 1.57 |
2016-09-27 | 18.69 | 5.72 | 8.13 | 0.95 | 8.20 | 3.45 | 4.72 | 14.98 | 9.92 | 4.24 | ... | 5.13 | 7.53 | 7.51 | 2.43 | 21.08 | 4.54 | 1.17 | 77160.7031 | 3.70 | 1.58 |
2016-09-28 | 18.49 | 5.85 | 8.31 | 0.95 | 8.27 | 3.52 | 4.76 | 15.08 | 9.97 | 4.20 | ... | 5.16 | 7.49 | 7.52 | 2.45 | 21.24 | 4.70 | 1.18 | 77677.7969 | 3.76 | 1.60 |
2016-09-29 | 18.40 | 6.19 | 8.13 | 0.96 | 8.20 | 3.59 | 4.41 | 15.07 | 9.93 | 4.19 | ... | 5.16 | 7.70 | 7.56 | 2.48 | 21.22 | 4.62 | 1.17 | 77076.7969 | 3.70 | 1.60 |
2016-09-30 | 18.17 | 6.30 | 8.04 | 0.95 | 8.16 | 3.57 | 4.26 | 14.89 | 10.05 | 4.13 | ... | 5.14 | 7.72 | 7.53 | 2.49 | 21.38 | 4.59 | 1.18 | 76488.3984 | 3.67 | 1.59 |
5 rows × 30 columns
dividends_and_splits= pd.DataFrame()
for symbol in symbols:
f = web.DataReader(symbol, 'yahoo-actions')
if len(f) > 0:
f['symbol'] = symbol
dividends_and_splits = pd.concat([dividends_and_splits, f])
Splits = dividends_and_splits[dividends_and_splits["action"] == 'SPLIT']
Dividends = dividends_and_splits[dividends_and_splits["action"] == 'DIVIDEND']
Splits
action | value | symbol | |
---|---|---|---|
2013-06-26 | SPLIT | 0.869565 | THYAO.IS |
2011-07-11 | SPLIT | 0.833333 | THYAO.IS |
2013-07-03 | SPLIT | 0.980392 | TRKCM.IS |
2012-07-16 | SPLIT | 0.869565 | TRKCM.IS |
2010-11-25 | SPLIT | 0.500000 | DOAS.IS |
2013-07-04 | SPLIT | 0.961538 | SISE.IS |
2012-07-10 | SPLIT | 0.909091 | SISE.IS |
2011-06-20 | SPLIT | 0.884956 | SISE.IS |
2013-04-12 | SPLIT | 0.884956 | EREGL.IS |
2012-04-30 | SPLIT | 0.699301 | EREGL.IS |
2011-03-15 | SPLIT | 0.746269 | EREGL.IS |
2010-07-02 | SPLIT | 0.250000 | PETKM.IS |
2010-01-18 | SPLIT | 0.040000 | AFYON.IS |
2010-06-16 | SPLIT | 0.500000 | KOZAL.IS |
2016-06-01 | SPLIT | 0.045455 | GOODY.IS |
2013-07-29 | SPLIT | 0.925926 | VAKFN.IS |
2012-06-15 | SPLIT | 0.833333 | VAKFN.IS |
2011-07-20 | SPLIT | 0.500000 | VAKFN.IS |
Dividends.head()
action | value | symbol | |
---|---|---|---|
2016-05-30 | DIVIDEND | 0.245 | AEFES.IS |
2015-05-29 | DIVIDEND | 0.460 | AEFES.IS |
2013-05-30 | DIVIDEND | 0.450 | AEFES.IS |
2012-05-29 | DIVIDEND | 0.450 | AEFES.IS |
2011-05-27 | DIVIDEND | 0.480 | AEFES.IS |
order = {'symbol':'AKBNK.IS',
'shares':100,
'action':'buy',
'time':'2016-05-12'}
transaction = {'status':'accepted',
'symbol': 'GARAN',
'action':'buy',
'shares':100,
'price':5.2,
'commision':2,
'time':'2016-05-13'}
In real situation, when we pass the order to a brocker, the brocker responds with a transaction. We will simulate this situation with the following function.
# TODO: check user account's free cash and update it accordingly
def execute_order(order, holdings):
'Simulates the broker/market and creates a transaction.'
transaction = deepcopy(order)
symbol, shares, time = order['symbol'], order['shares'], order['time']
if order['action']=='sell':
if (holdings is None or
not (symbol in holdings.index) or
holdings.loc[symbol]['shares'] < order['shares']):
warnings.warn('Your order ' + str(order) + ' is rejected.')
transaction['status'] = 'rejected'
return transaction
transaction['status'] = 'accepted'
price = get_price(symbol, time)
commision = commision_calculation(order, price)
transaction['price'], transaction['commision'] = price, commision
return transaction
def get_price(symbol, time = None, price_source=prices):
'Returns the last price of the symbol. We assume that prices is a pandas object.'
if time is None:
time = str(datetime.datetime.now())
try:
closest_time = (price_source.index[time >= price_source.index]).sort_values()[-1]
return price_source[symbol].loc[closest_time]
except ValueError:
raise ValueError("We don't have historical data for an order at " + order_time)
except IndexError:
raise IndexError("We don't have historical data for an order at " + order_time)
def commision_calculation(order, price, commission_ratio=0.0001):
'Calculates commision to be paid.'
return order['shares']*price*commission_ratio
def current_time(prices=prices):
'Returns the maximum date from the prices table.'
return max(prices.index).strftime("%Y-%m-%d")
execute_order(order, [])
{'action': 'buy', 'commision': 0.076999999999999999, 'price': 7.7000000000000002, 'shares': 100, 'status': 'accepted', 'symbol': 'AKBNK.IS', 'time': '2016-05-12'}
TODO: make a real example
Every time we have an accepted buy order we create a position. A trade is a matching of buy/sell transactions of the same symbol. We need these trade objects in order to calculate the current cost of the portfolio and realized profits.
Transactions
Cost
In order to calculate $x $, we need to match the sell order at t3 with the buy orders t1 and t2. For the matching we assume first-in first-out rule. We first match the sell order at t3 with the buy order at t1 and then the remaining with the order at t2.
def apply_transaction(transaction, positions, trades):
'Update positions and trades with the transaction.'
if transaction["status"] == "accepted":
symbol, action, shares = transaction["symbol"], transaction["action"], transaction["shares"]
price, time = transaction["price"], transaction['time']
if action == "buy":
position = {'type':'long',
'symbol':symbol,
'initial_shares':shares,
'shares':shares,
'price': price,
'cost': price*shares,
'time': time}
positions.append(position)
else:
match_sell_transaction_to_position(transaction, positions, trades)
def match_sell_transaction_to_position(transaction, positions, trades):
"""We will select the positions with the same symbol and order them according to time desc.
Until we finish the order's volume we match it with a position. If a position is fulfilled,
we continue with the next one in the order. We create a trade, we remove the amount traded
from the position. If the position's volume is empty we remove the position from the list.
Assumption: Since the broker rejects sells orders greater then our holdings,
we assume that transaction.shares <= sum(positions.shares)."""
sorted(positions, key=lambda k: k['time'])
shares, time, symbol = transaction["shares"], transaction["time"], transaction["symbol"]
for position in positions:
if not shares > 0:
break
if position["symbol"] == transaction["symbol"] and position["shares"] > 0:
traded_shares = min(shares, position['shares'])
buy_price, sell_price = position["price"], transaction["price"]
profit = (sell_price - buy_price) * traded_shares
trade = {'symbol':symbol,
'shares':traded_shares,
'time':time,
'buy_price': buy_price,
'sell_price': sell_price,
'profit': profit}
trades.append(trade)
shares -= traded_shares
position["shares"] = position["shares"] - traded_shares
position["cost"] = position["shares"] * buy_price
def calculate_portfolio(positions):
if len(positions) == 0:
return []
else:
temp = pd.DataFrame(positions)
return temp.pivot_table(index='symbol', aggfunc='sum', values=["cost", 'shares'])
orders = [
{'symbol':'GARAN.IS', 'shares':100, 'action':'buy', 'time':'2016-05-15 10:00:00'},
{'symbol':'GARAN.IS', 'shares':100, 'action':'buy', 'time':'2016-05-20 11:00:00'},
{'symbol':'GARAN.IS', 'shares':120, 'action':'sel', 'time':'2016-05-22 09:50:00'},
{'symbol':'AKBNK.IS', 'shares':100, 'action':'buy', 'time':'2016-05-20 16:30:00'},
{'symbol':'AKBNK.IS', 'shares':100, 'action':'buy', 'time':'2016-05-21 10:57:23'},
{'symbol':'AKBNK.IS', 'shares':220, 'action':'buy', 'time':'2016-05-24 10:00:00'},
{'symbol':'AKBNK.IS', 'shares':200, 'action':'sell', 'time':'2016-05-24 12:00:00'},
{'symbol':'AKBNK.IS', 'shares':110, 'action':'sell', 'time':'2016-05-27 00:00:00'},
{'symbol':'ZOREN.IS', 'shares':50, 'action':'sell', 'time':'2016-05-28 00:00:00'},
]
pd.DataFrame(orders)
action | shares | symbol | time | |
---|---|---|---|---|
0 | buy | 100 | GARAN.IS | 2016-05-15 10:00:00 |
1 | buy | 100 | GARAN.IS | 2016-05-20 11:00:00 |
2 | sel | 120 | GARAN.IS | 2016-05-22 09:50:00 |
3 | buy | 100 | AKBNK.IS | 2016-05-20 16:30:00 |
4 | buy | 100 | AKBNK.IS | 2016-05-21 10:57:23 |
5 | buy | 220 | AKBNK.IS | 2016-05-24 10:00:00 |
6 | sell | 200 | AKBNK.IS | 2016-05-24 12:00:00 |
7 | sell | 110 | AKBNK.IS | 2016-05-27 00:00:00 |
8 | sell | 50 | ZOREN.IS | 2016-05-28 00:00:00 |
def execute_orders(orders, transactions, positions, trades):
"""Calls execute_order function for each order in the order list.
Updates transaction, position and trade lists.
"""
portfolio = calculate_portfolio(positions)
for order in orders:
transaction = execute_order(order, portfolio)
transactions.append(transaction)
apply_transaction(transaction, positions, trades)
portfolio = calculate_portfolio(positions)
transactions, positions, trades = [], [], []
execute_orders(orders, transactions, positions, trades);
/home/can/.local/lib/python2.7/site-packages/ipykernel/__main__.py:12: UserWarning: Your order {'action': 'sell', 'symbol': 'ZOREN.IS', 'shares': 50, 'time': '2016-05-28 00:00:00'} is rejected.
pd.DataFrame(transactions)
action | commision | price | shares | status | symbol | time | |
---|---|---|---|---|---|---|---|
0 | buy | 0.07510 | 7.51 | 100 | accepted | GARAN.IS | 2016-05-15 10:00:00 |
1 | buy | 0.07250 | 7.25 | 100 | accepted | GARAN.IS | 2016-05-20 11:00:00 |
2 | sel | 0.08700 | 7.25 | 120 | accepted | GARAN.IS | 2016-05-22 09:50:00 |
3 | buy | 0.07500 | 7.50 | 100 | accepted | AKBNK.IS | 2016-05-20 16:30:00 |
4 | buy | 0.07500 | 7.50 | 100 | accepted | AKBNK.IS | 2016-05-21 10:57:23 |
5 | buy | 0.17710 | 8.05 | 220 | accepted | AKBNK.IS | 2016-05-24 10:00:00 |
6 | sell | 0.16100 | 8.05 | 200 | accepted | AKBNK.IS | 2016-05-24 12:00:00 |
7 | sell | 0.08745 | 7.95 | 110 | accepted | AKBNK.IS | 2016-05-27 00:00:00 |
8 | sell | NaN | NaN | 50 | rejected | ZOREN.IS | 2016-05-28 00:00:00 |
def summary(transactions, positions, trades):
print "***Transactions***".center(70)
print '-' * 70
print pd.DataFrame(transactions)
print ''
print "***Positions***".center(70)
print '-' * 70
print pd.DataFrame(positions)
print ''
print "***Trades***".center(70)
print '-' * 70
print pd.DataFrame(trades)
summary(transactions, positions, trades)
***Transactions*** ---------------------------------------------------------------------- action commision price shares status symbol time 0 buy 0.07510 7.51 100 accepted GARAN.IS 2016-05-15 10:00:00 1 buy 0.07250 7.25 100 accepted GARAN.IS 2016-05-20 11:00:00 2 sel 0.08700 7.25 120 accepted GARAN.IS 2016-05-22 09:50:00 3 buy 0.07500 7.50 100 accepted AKBNK.IS 2016-05-20 16:30:00 4 buy 0.07500 7.50 100 accepted AKBNK.IS 2016-05-21 10:57:23 5 buy 0.17710 8.05 220 accepted AKBNK.IS 2016-05-24 10:00:00 6 sell 0.16100 8.05 200 accepted AKBNK.IS 2016-05-24 12:00:00 7 sell 0.08745 7.95 110 accepted AKBNK.IS 2016-05-27 00:00:00 8 sell NaN NaN 50 rejected ZOREN.IS 2016-05-28 00:00:00 ***Positions*** ---------------------------------------------------------------------- cost initial_shares price shares symbol time type 0 0.0 100 7.51 0 GARAN.IS 2016-05-15 10:00:00 long 1 580.0 100 7.25 80 GARAN.IS 2016-05-20 11:00:00 long 2 0.0 100 7.50 0 AKBNK.IS 2016-05-20 16:30:00 long 3 0.0 100 7.50 0 AKBNK.IS 2016-05-21 10:57:23 long 4 885.5 220 8.05 110 AKBNK.IS 2016-05-24 10:00:00 long ***Trades*** ---------------------------------------------------------------------- buy_price profit sell_price shares symbol time 0 7.51 -26.0 7.25 100 GARAN.IS 2016-05-22 09:50:00 1 7.25 0.0 7.25 20 GARAN.IS 2016-05-22 09:50:00 2 7.50 55.0 8.05 100 AKBNK.IS 2016-05-24 12:00:00 3 7.50 55.0 8.05 100 AKBNK.IS 2016-05-24 12:00:00 4 8.05 -11.0 7.95 110 AKBNK.IS 2016-05-27 00:00:00
An asset is financial instruments that we own. The assets can be calculated using transaction reports. Market value is the current value of an asset. It represent the value as if we want to sell the asset right now. It is calculated by some estimation of the current price of the corresponding symbol. The collection of assets that we own are called our portfolio.
portfolio = calculate_portfolio(positions)
portfolio
cost | shares | |
---|---|---|
symbol | ||
AKBNK.IS | 885.5 | 110 |
GARAN.IS | 580.0 | 80 |
x = pd.Series({"GARAN.IS": get_price("GARAN.IS"), "AKBNK.IS": get_price("AKBNK.IS")})
portfolio["current_price"] = x
portfolio["shares"] * portfolio["current_price"]
symbol AKBNK.IS 884.4 GARAN.IS 636.0 dtype: float64
def get_prices(assets, time = None):
return {symbol: get_price(symbol, time) for symbol in assets}
pd.Series(get_prices(portfolio.index))
AKBNK.IS 8.04 GARAN.IS 7.95 dtype: float64
portfolio["shares"] / 2
symbol AKBNK.IS 55.0 GARAN.IS 40.0 Name: shares, dtype: float64
def current_performance(portfolio, time=None):
portfolio["current_price"] = pd.Series(get_prices(portfolio.index, time))
portfolio["market_value"] = portfolio["shares"] * portfolio["current_price"]
portfolio["profit"] = portfolio["market_value"] - portfolio["cost"]
total_market_value = portfolio.market_value.sum()
portfolio["weight"] = portfolio["market_value"] / total_market_value
current_performance(portfolio)
portfolio
cost | shares | current_price | market_value | profit | weight | |
---|---|---|---|---|---|---|
symbol | ||||||
AKBNK.IS | 885.5 | 110 | 8.04 | 884.4 | -1.1 | 0.581689 |
GARAN.IS | 580.0 | 80 | 7.95 | 636.0 | 56.0 | 0.418311 |
def historical_performance(transactions, prices):
"Returns historical market value of a portfolio."
starting_date = min(transactions, key=lambda x: x["time"])["time"]
ending_date = datetime.datetime.now()
symbols = set([t["symbol"] for t in transactions if t["status"]=="accepted"] )
symbol_price = (prices.loc[starting_date:ending_date][list(symbols)])
holdings_list = holdings(transactions)
return (holdings_list
.fillna(method='ffill')
.reindex(symbol_price.index.union(holdings_list.index))
.fillna(method='ffill')
.reindex(symbol_price.index)
.mul(symbol_price).sum(axis=1)
)
def holdings(transactions):
t = pd.DataFrame(transactions)
t["sign"] = t["action"].apply(lambda x: 1 if x=="buy" else -1)
t["signed_shares"] = t["sign"] * t["shares"]
t["time"] = pd.to_datetime(t["time"])
return (t.query("status == 'accepted'")
.pivot_table(values="signed_shares", columns="symbol", index="time")
.cumsum()
)
symbols = set([t["symbol"] for t in transactions if t["status"]=="accepted"] )
starting_date = min(transactions, key=lambda x: x["time"])["time"]
ending_date = datetime.datetime.now()
symbol_price = (prices.loc[starting_date:ending_date][list(symbols)])
def compare_with_benchmark(historical_value, benchmark_symbol="XU100.IS"):
algo = (historical_value[historical_value > 0].pct_change() + 1).cumprod()
algo.name = "Algorithm"
algo.plot(legend=True)
print "Algorithm performance:", (algo.ix[-1] - 1)*100
start_date = historical_value.index[0]
benchmark = (prices[benchmark_symbol].dropna().pct_change().loc[start_date:] + 1).cumprod()
benchmark.name = "Benchmark"
benchmark.plot(legend = True, figsize=[15,10])
print "Benchmark performance:", (benchmark.ix[-1] - 1)*100
historical_performance(transactions, prices).plot(figsize= [15,10])
<matplotlib.axes._subplots.AxesSubplot at 0x7fc0b3324410>
def paid_dividends(transactions, dividends):
start_date = min(transactions, key=lambda x: x["time"])["time"]
end_date = datetime.datetime.now()
H= holdings(transactions)
H.index = pd.to_datetime(H.index)
H = (H.reindex(pd.date_range(start=start_date, end=end_date, freq='D'))
.fillna(method='ffill')
.fillna(0))
return (pd.melt(Dividends[Dividends.symbol.apply(lambda x: x in H.columns)]
.reset_index()
.rename(columns={'index':'time'})
.pivot_table(values="value", columns="symbol", index = 'time')
.reindex(H.index)
.mul(H)
.reset_index()
.rename(columns={'index':'time'})
, id_vars = 'time', var_name= 'symbol', value_name='paid_dividend'
)
).query("paid_dividend > 0")
paid_dividends(transactions, Dividends)
time | symbol | paid_dividend |
---|
def rebalance(portfolio, target_weights, target_value = None, time = None):
"""New weights is a dictionary of {symbol: weights}.
Creates orders to make portfolio's weight 'new weights'.
Time indicates execution of rebalance operation.
"""
if time is None:
time = current_time()
if target_value is None:
target_value = portfolio.market_value.sum()
if len(portfolio)>0:
target_weights = {s:target_weights[s] if s in target_weights.keys() else 0
for s in set(portfolio.index | target_weights.keys())}
# check if the weights sum up to 1.
assert(sum(target_weights.values()) == 1)
rebalance_orders = []
target_market_value = {s:target_weights[s]*target_value for s in target_weights.keys()}
for symbol, weight in target_weights.iteritems():
if len(portfolio)>0 and symbol in portfolio.index:
delta_value = target_market_value[symbol] - portfolio["market_value"].loc[symbol]
if weight:
delta_lot = int(abs(delta_value / get_price(symbol, time)))
else:
delta_lot = portfolio["shares"].loc[symbol]
if delta_lot:
if delta_value > 0:
action = 'buy'
else:
action = 'sell'
order = {'symbol': symbol, 'shares': delta_lot, 'action': action, 'time': time}
rebalance_orders.append(order)
else:
delta_lot = int(target_market_value[symbol] / get_price(symbol, time))
order = {'symbol': symbol, 'shares': delta_lot, 'action': 'buy', 'time': time}
rebalance_orders.append(order)
return rebalance_orders
portfolio
cost | shares | current_price | market_value | profit | weight | |
---|---|---|---|---|---|---|
symbol | ||||||
AKBNK.IS | 885.5 | 110 | 8.04 | 884.4 | -1.1 | 0.581689 |
GARAN.IS | 580.0 | 80 | 7.95 | 636.0 | 56.0 | 0.418311 |
portfolio["market_value"].loc['AKBNK.IS']
884.39999999999986
orders_to_rebalance = rebalance(portfolio, {"AKBNK.IS":0.50, "GARAN.IS": 0.20, "ZOREN.IS": 0.30 })
pd.DataFrame(orders_to_rebalance)
action | shares | symbol | time | |
---|---|---|---|---|
0 | sell | 41 | GARAN.IS | 2016-09-30 |
1 | buy | 286 | ZOREN.IS | 2016-09-30 |
2 | sell | 15 | AKBNK.IS | 2016-09-30 |
execute_orders(orders_to_rebalance, transactions, positions, trades)
summary(transactions, positions, trades)
***Transactions*** ---------------------------------------------------------------------- action commision price shares status symbol time 0 buy 0.075100 7.51 100 accepted GARAN.IS 2016-05-15 10:00:00 1 buy 0.072500 7.25 100 accepted GARAN.IS 2016-05-20 11:00:00 2 sel 0.087000 7.25 120 accepted GARAN.IS 2016-05-22 09:50:00 3 buy 0.075000 7.50 100 accepted AKBNK.IS 2016-05-20 16:30:00 4 buy 0.075000 7.50 100 accepted AKBNK.IS 2016-05-21 10:57:23 5 buy 0.177100 8.05 220 accepted AKBNK.IS 2016-05-24 10:00:00 6 sell 0.161000 8.05 200 accepted AKBNK.IS 2016-05-24 12:00:00 7 sell 0.087450 7.95 110 accepted AKBNK.IS 2016-05-27 00:00:00 8 sell NaN NaN 50 rejected ZOREN.IS 2016-05-28 00:00:00 9 sell 0.032595 7.95 41 accepted GARAN.IS 2016-09-30 10 buy 0.045474 1.59 286 accepted ZOREN.IS 2016-09-30 11 sell 0.012060 8.04 15 accepted AKBNK.IS 2016-09-30 ***Positions*** ---------------------------------------------------------------------- cost initial_shares price shares symbol time type 0 0.00 100 7.51 0 GARAN.IS 2016-05-15 10:00:00 long 1 282.75 100 7.25 39 GARAN.IS 2016-05-20 11:00:00 long 2 0.00 100 7.50 0 AKBNK.IS 2016-05-20 16:30:00 long 3 0.00 100 7.50 0 AKBNK.IS 2016-05-21 10:57:23 long 4 764.75 220 8.05 95 AKBNK.IS 2016-05-24 10:00:00 long 5 454.74 286 1.59 286 ZOREN.IS 2016-09-30 long ***Trades*** ---------------------------------------------------------------------- buy_price profit sell_price shares symbol time 0 7.51 -26.00 7.25 100 GARAN.IS 2016-05-22 09:50:00 1 7.25 0.00 7.25 20 GARAN.IS 2016-05-22 09:50:00 2 7.50 55.00 8.05 100 AKBNK.IS 2016-05-24 12:00:00 3 7.50 55.00 8.05 100 AKBNK.IS 2016-05-24 12:00:00 4 8.05 -11.00 7.95 110 AKBNK.IS 2016-05-27 00:00:00 5 7.25 28.70 7.95 41 GARAN.IS 2016-09-30 6 8.05 -0.15 8.04 15 AKBNK.IS 2016-09-30
portfolio = calculate_portfolio(positions)
portfolio
cost | shares | |
---|---|---|
symbol | ||
AKBNK.IS | 764.75 | 95 |
GARAN.IS | 282.75 | 39 |
ZOREN.IS | 454.74 | 286 |
current_performance(portfolio)
portfolio
cost | shares | current_price | market_value | profit | weight | |
---|---|---|---|---|---|---|
symbol | ||||||
AKBNK.IS | 764.75 | 95 | 8.04 | 763.80 | -0.95 | 0.499676 |
GARAN.IS | 282.75 | 39 | 7.95 | 310.05 | 27.30 | 0.202834 |
ZOREN.IS | 454.74 | 286 | 1.59 | 454.74 | 0.00 | 0.297490 |
portfolio, transactions, positions, trades = [], [], [], []
orders_to_rebalance = rebalance([], {'AKBNK.IS': 0.50, 'GARAN.IS': 0.50}, 1000000)
pd.DataFrame(orders_to_rebalance)
action | shares | symbol | time | |
---|---|---|---|---|
0 | buy | 62893 | GARAN.IS | 2016-09-30 |
1 | buy | 62189 | AKBNK.IS | 2016-09-30 |
execute_orders(orders_to_rebalance, transactions, positions, trades)
summary(transactions, positions, trades)
***Transactions*** ---------------------------------------------------------------------- action commision price shares status symbol time 0 buy 49.999935 7.95 62893 accepted GARAN.IS 2016-09-30 1 buy 49.999956 8.04 62189 accepted AKBNK.IS 2016-09-30 ***Positions*** ---------------------------------------------------------------------- cost initial_shares price shares symbol time type 0 499999.35 62893 7.95 62893 GARAN.IS 2016-09-30 long 1 499999.56 62189 8.04 62189 AKBNK.IS 2016-09-30 long ***Trades*** ---------------------------------------------------------------------- Empty DataFrame Columns: [] Index: []
portfolio = calculate_portfolio(positions)
current_performance(portfolio)
portfolio
cost | shares | current_price | market_value | profit | weight | |
---|---|---|---|---|---|---|
symbol | ||||||
AKBNK.IS | 499999.56 | 62189 | 8.04 | 499999.56 | 0.0 | 0.5 |
GARAN.IS | 499999.35 | 62893 | 7.95 | 499999.35 | 0.0 | 0.5 |
capital_base = 100000
start, end = np.datetime64('2016-01-20 00:00:00'), np.datetime64('2016-07-18 00:00:00')
running_points = [date for date in prices.index if start <= date <= end]
http://markets.ft.com/data/lexicon/term/beta
We use Beta 5Y from the Multex Ratios and Statistics table, which is provided to us by Reuters. The Market Guide Beta is the slope of the 60 month regression line of the percentage price change of the stock relative to the percentage price change of the S&P 500. Beta values are not calculated if less than 24 months of pricing is available.
def beta(price_data, start, end):
returns = (prices.loc[start:end]
.resample('3BMS', 'first')
.pct_change()
.dropna())
beta_values = {symbol: linregress(returns["XU100.IS"], returns[symbol])[0]
for symbol in price_data.columns if symbol != 'XU100.IS'}
return beta_values
portfolio, transactions, positions, trades = [], [], [], []
for t in running_points:
time = t.strftime("%Y-%m-%d")
if t in pd.date_range(start=running_points[0], periods=12, freq='BM'):
print t
print '-'*20
beta_values = beta(prices, prices.index[0], t)
for s in sorted(beta_values, key=beta_values.get, reverse=True):
print s, beta_values[s]
n = 5
new_weights = {s: 1./n for s in sorted(beta_values, key=beta_values.get, reverse=True)[:n]}
print new_weights
target_value = None if len(portfolio) else capital_base
if len(portfolio) > 0:
current_performance(portfolio, time)
rebalance_orders = rebalance(portfolio, new_weights, target_value, time)
print "Before Orders"
print "-"*20
print portfolio
print " "
print "Orders"
print "-"*20
print pd.DataFrame(rebalance_orders)
print " "
execute_orders(rebalance_orders, transactions, positions, trades)
portfolio = calculate_portfolio(positions)
current_performance(portfolio, time)
print "After Orders"
print "-"*20
print portfolio
print " "
portfolio = calculate_portfolio(positions)
2016-01-29 00:00:00 -------------------- AFYON.IS 56.9642159504 GOODY.IS 6.87604665207 DOAS.IS 5.19504241764 AEFES.IS 3.51989365886 KOZAL.IS 3.3448762139 AKSA.IS 3.12012336438 EREGL.IS 2.84900427814 SISE.IS 2.51218079997 TCELL.IS 2.10369051414 FROTO.IS 2.09457851314 PETKM.IS 1.81512146095 TRKCM.IS 1.48578088376 THYAO.IS 1.18962314346 MGROS.IS 1.15606357034 TKFEN.IS 1.00811513171 GARAN.IS 1.00615148771 AKBNK.IS 0.886587616544 YKBNK.IS 0.867160616649 HALKB.IS 0.855486536853 ALARK.IS 0.820330070269 VAKBN.IS 0.750041809138 ZOREN.IS 0.646334486257 VAKFN.IS 0.251506076805 CIMSA.IS -0.00851550187079 AKENR.IS -0.796155439582 ULKER.IS -1.00029164062 KARSN.IS -1.51552933437 TMSN.IS -1.73699367046 BJKAS.IS -3.00339814457 {'DOAS.IS': 0.2, 'AFYON.IS': 0.2, 'AEFES.IS': 0.2, 'KOZAL.IS': 0.2, 'GOODY.IS': 0.2} Before Orders -------------------- [] Orders -------------------- action shares symbol time 0 buy 2059 DOAS.IS 2016-01-29 1 buy 3384 AFYON.IS 2016-01-29 2 buy 1108 AEFES.IS 2016-01-29 3 buy 1594 KOZAL.IS 2016-01-29 4 buy 417101 GOODY.IS 2016-01-29 After Orders -------------------- cost shares current_price market_value profit weight symbol AEFES.IS 19999.40000 1108 18.05000 19999.40000 0.0 0.200036 AFYON.IS 19999.44000 3384 5.91000 19999.44000 0.0 0.200036 DOAS.IS 19991.44870 2059 9.70930 19991.44870 0.0 0.199956 GOODY.IS 19999.99295 417101 0.04795 19999.99295 0.0 0.200042 KOZAL.IS 19988.76000 1594 12.54000 19988.76000 0.0 0.199930 2016-02-29 00:00:00 -------------------- AFYON.IS 56.9642159504 GOODY.IS 6.87604665207 DOAS.IS 5.19504241764 AEFES.IS 3.51989365886 KOZAL.IS 3.3448762139 AKSA.IS 3.12012336438 EREGL.IS 2.84900427814 SISE.IS 2.51218079997 TCELL.IS 2.10369051414 FROTO.IS 2.09457851314 PETKM.IS 1.81512146095 TRKCM.IS 1.48578088376 THYAO.IS 1.18962314346 MGROS.IS 1.15606357034 TKFEN.IS 1.00811513171 GARAN.IS 1.00615148771 AKBNK.IS 0.886587616544 YKBNK.IS 0.867160616649 HALKB.IS 0.855486536853 ALARK.IS 0.820330070269 VAKBN.IS 0.750041809138 ZOREN.IS 0.646334486257 VAKFN.IS 0.251506076805 CIMSA.IS -0.00851550187079 AKENR.IS -0.796155439582 ULKER.IS -1.00029164062 KARSN.IS -1.51552933437 TMSN.IS -1.73699367046 BJKAS.IS -3.00339814457 {'DOAS.IS': 0.2, 'AFYON.IS': 0.2, 'AEFES.IS': 0.2, 'KOZAL.IS': 0.2, 'GOODY.IS': 0.2} Before Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 19999.40000 1108 16.98000 18813.84000 -1185.56000 AFYON.IS 19999.44000 3384 5.98000 20236.32000 236.88000 DOAS.IS 19991.44870 2059 10.08480 20764.60320 773.15450 GOODY.IS 19999.99295 417101 0.04646 19378.51246 -621.48049 KOZAL.IS 19988.76000 1594 16.24000 25886.56000 5897.80000 weight symbol AEFES.IS 0.179043 AFYON.IS 0.192580 DOAS.IS 0.197608 GOODY.IS 0.184417 KOZAL.IS 0.246351 Orders -------------------- action shares symbol time 0 buy 24 DOAS.IS 2016-02-29 1 buy 130 AFYON.IS 2016-02-29 2 buy 129 AEFES.IS 2016-02-29 3 sell 299 KOZAL.IS 2016-02-29 4 buy 35244 GOODY.IS 2016-02-29 After Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 22189.82000 1237 16.98000 21004.2600 -1185.56000 AFYON.IS 20776.84000 3514 5.98000 21013.7200 236.88000 DOAS.IS 20233.48390 2083 10.08480 21006.6384 773.15450 GOODY.IS 21637.42919 452345 0.04646 21015.9487 -621.48049 KOZAL.IS 16239.30000 1295 16.24000 21030.8000 4791.50000 weight symbol AEFES.IS 0.199905 AFYON.IS 0.199995 DOAS.IS 0.199927 GOODY.IS 0.200016 KOZAL.IS 0.200157 2016-03-31 00:00:00 -------------------- AFYON.IS 56.9642159504 GOODY.IS 6.87604665207 DOAS.IS 5.19504241764 AEFES.IS 3.51989365886 KOZAL.IS 3.3448762139 AKSA.IS 3.12012336438 EREGL.IS 2.84900427814 SISE.IS 2.51218079997 TCELL.IS 2.10369051414 FROTO.IS 2.09457851314 PETKM.IS 1.81512146095 TRKCM.IS 1.48578088376 THYAO.IS 1.18962314346 MGROS.IS 1.15606357034 TKFEN.IS 1.00811513171 GARAN.IS 1.00615148771 AKBNK.IS 0.886587616544 YKBNK.IS 0.867160616649 HALKB.IS 0.855486536853 ALARK.IS 0.820330070269 VAKBN.IS 0.750041809138 ZOREN.IS 0.646334486257 VAKFN.IS 0.251506076805 CIMSA.IS -0.00851550187079 AKENR.IS -0.796155439582 ULKER.IS -1.00029164062 KARSN.IS -1.51552933437 TMSN.IS -1.73699367046 BJKAS.IS -3.00339814457 {'DOAS.IS': 0.2, 'AFYON.IS': 0.2, 'AEFES.IS': 0.2, 'KOZAL.IS': 0.2, 'GOODY.IS': 0.2} Before Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 22189.82000 1237 21.16000 26174.92000 3985.10000 AFYON.IS 20776.84000 3514 6.37000 22384.18000 1607.34000 DOAS.IS 20233.48390 2083 11.24710 23427.70930 3194.22540 GOODY.IS 21637.42919 452345 0.08757 39611.85165 17974.42246 KOZAL.IS 16239.30000 1295 18.07000 23400.65000 7161.35000 weight symbol AEFES.IS 0.193889 AFYON.IS 0.165810 DOAS.IS 0.173539 GOODY.IS 0.293423 KOZAL.IS 0.173339 Orders -------------------- action shares symbol time 0 buy 317 DOAS.IS 2016-03-31 1 buy 724 AFYON.IS 2016-03-31 2 buy 38 AEFES.IS 2016-03-31 3 buy 199 KOZAL.IS 2016-03-31 4 sell 144021 GOODY.IS 2016-03-31 After Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 22993.90000 1275 21.16000 26979.00000 3985.10000 AFYON.IS 25388.72000 4238 6.37000 26996.06000 1607.34000 DOAS.IS 23798.81460 2400 11.24710 26993.04000 3194.22540 GOODY.IS 14731.62224 308324 0.08757 26999.93268 12268.31044 KOZAL.IS 19835.23000 1494 18.07000 26996.58000 7161.35000 weight symbol AEFES.IS 0.199897 AFYON.IS 0.200023 DOAS.IS 0.200001 GOODY.IS 0.200052 KOZAL.IS 0.200027 2016-04-29 00:00:00 -------------------- BJKAS.IS 5.33745899346 GOODY.IS 3.70296155031 AFYON.IS 2.73888471627 EREGL.IS 2.26335412215 KOZAL.IS 2.17678028137 TKFEN.IS 1.91104031464 YKBNK.IS 1.47010564428 DOAS.IS 1.28165996194 VAKBN.IS 1.27942651058 VAKFN.IS 1.25114330665 PETKM.IS 1.2243493208 FROTO.IS 1.18892366153 TCELL.IS 1.17502050664 AKBNK.IS 1.15415096839 TRKCM.IS 1.15112004053 AEFES.IS 1.0820661819 ALARK.IS 1.04582594283 GARAN.IS 0.924882254881 SISE.IS 0.819848136752 ULKER.IS 0.651242173138 THYAO.IS 0.577994374221 MGROS.IS 0.432742947264 AKENR.IS 0.411572932002 CIMSA.IS 0.409761734264 HALKB.IS 0.29317300613 ZOREN.IS 0.177975826959 AKSA.IS -0.164770083225 KARSN.IS -0.444213608009 TMSN.IS -1.12383635356 {'AFYON.IS': 0.2, 'BJKAS.IS': 0.2, 'EREGL.IS': 0.2, 'GOODY.IS': 0.2, 'KOZAL.IS': 0.2} Before Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 22993.90000 1275 21.72000 27693.00000 4699.10000 AFYON.IS 25388.72000 4238 6.15000 26063.70000 674.98000 DOAS.IS 23798.81460 2400 12.08000 28992.00000 5193.18540 GOODY.IS 14731.62224 308324 0.08822 27200.34328 12468.72104 KOZAL.IS 19835.23000 1494 18.30000 27340.20000 7504.97000 weight symbol AEFES.IS 0.201713 AFYON.IS 0.189845 DOAS.IS 0.211175 GOODY.IS 0.198124 KOZAL.IS 0.199143 Orders -------------------- action shares symbol time 0 buy 5310 BJKAS.IS 2016-04-29 1 buy 6309 EREGL.IS 2016-04-29 2 sell 1275 AEFES.IS 2016-04-29 3 buy 6 KOZAL.IS 2016-04-29 4 sell 2400 DOAS.IS 2016-04-29 5 buy 226 AFYON.IS 2016-04-29 6 buy 2918 GOODY.IS 2016-04-29 After Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 0.00000 0 21.72000 0.00000 0.00000 AFYON.IS 26778.62000 4464 6.15000 27453.60000 674.98000 BJKAS.IS 27452.70000 5310 5.17000 27452.70000 0.00000 DOAS.IS 0.00000 0 12.08000 0.00000 0.00000 EREGL.IS 27454.18131 6309 4.35159 27454.18131 0.00000 GOODY.IS 14989.04820 311242 0.08822 27457.76924 12468.72104 KOZAL.IS 19945.03000 1500 18.30000 27450.00000 7504.97000 weight symbol AEFES.IS 0.000000 AFYON.IS 0.200000 BJKAS.IS 0.199993 DOAS.IS 0.000000 EREGL.IS 0.200004 GOODY.IS 0.200030 KOZAL.IS 0.199973 2016-05-31 00:00:00 -------------------- BJKAS.IS 5.33745899346 GOODY.IS 3.70296155031 AFYON.IS 2.73888471627 EREGL.IS 2.26335412215 KOZAL.IS 2.17678028137 TKFEN.IS 1.91104031464 YKBNK.IS 1.47010564428 DOAS.IS 1.28165996194 VAKBN.IS 1.27942651058 VAKFN.IS 1.25114330665 PETKM.IS 1.2243493208 FROTO.IS 1.18892366153 TCELL.IS 1.17502050664 AKBNK.IS 1.15415096839 TRKCM.IS 1.15112004053 AEFES.IS 1.0820661819 ALARK.IS 1.04582594283 GARAN.IS 0.924882254881 SISE.IS 0.819848136752 ULKER.IS 0.651242173138 THYAO.IS 0.577994374221 MGROS.IS 0.432742947264 AKENR.IS 0.411572932002 CIMSA.IS 0.409761734264 HALKB.IS 0.29317300613 ZOREN.IS 0.177975826959 AKSA.IS -0.164770083225 KARSN.IS -0.444213608009 TMSN.IS -1.12383635356 {'AFYON.IS': 0.2, 'BJKAS.IS': 0.2, 'EREGL.IS': 0.2, 'GOODY.IS': 0.2, 'KOZAL.IS': 0.2} Before Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 0.00000 0 18.70000 0.000000e+00 0.000000e+00 AFYON.IS 26778.62000 4464 5.84000 2.606976e+04 -7.088600e+02 BJKAS.IS 27452.70000 5310 3.22000 1.709820e+04 -1.035450e+04 DOAS.IS 0.00000 0 10.92000 0.000000e+00 0.000000e+00 EREGL.IS 27454.18131 6309 4.12000 2.599308e+04 -1.461101e+03 GOODY.IS 14989.04820 311242 4.69645 1.461732e+06 1.446743e+06 KOZAL.IS 19945.03000 1500 13.74000 2.061000e+04 6.649700e+02 weight symbol AEFES.IS 0.000000 AFYON.IS 0.016803 BJKAS.IS 0.011020 DOAS.IS 0.000000 EREGL.IS 0.016753 GOODY.IS 0.942139 KOZAL.IS 0.013284 Orders -------------------- action shares symbol time 0 buy 91056 BJKAS.IS 2016-05-31 1 buy 69006 EREGL.IS 2016-05-31 2 buy 21083 KOZAL.IS 2016-05-31 3 buy 48669 AFYON.IS 2016-05-31 4 sell 245170 GOODY.IS 2016-05-31 After Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 0.00000 0 18.70000 0.0000 0.00000 AFYON.IS 311005.58000 53133 5.84000 310296.7200 -708.86000 BJKAS.IS 320653.02000 96366 3.22000 310298.5200 -10354.50000 DOAS.IS 0.00000 0 10.92000 0.0000 0.00000 EREGL.IS 311758.90131 75315 4.12000 310297.8000 -1461.10131 GOODY.IS 3233.14670 66072 4.69645 310303.8444 307070.69770 KOZAL.IS 309625.45000 22583 13.74000 310290.4200 664.97000 weight symbol AEFES.IS 0.000000 AFYON.IS 0.200000 BJKAS.IS 0.200001 DOAS.IS 0.000000 EREGL.IS 0.200000 GOODY.IS 0.200004 KOZAL.IS 0.199995 2016-06-30 00:00:00 -------------------- BJKAS.IS 5.33745899346 GOODY.IS 3.70296155031 AFYON.IS 2.73888471627 EREGL.IS 2.26335412215 KOZAL.IS 2.17678028137 TKFEN.IS 1.91104031464 YKBNK.IS 1.47010564428 DOAS.IS 1.28165996194 VAKBN.IS 1.27942651058 VAKFN.IS 1.25114330665 PETKM.IS 1.2243493208 FROTO.IS 1.18892366153 TCELL.IS 1.17502050664 AKBNK.IS 1.15415096839 TRKCM.IS 1.15112004053 AEFES.IS 1.0820661819 ALARK.IS 1.04582594283 GARAN.IS 0.924882254881 SISE.IS 0.819848136752 ULKER.IS 0.651242173138 THYAO.IS 0.577994374221 MGROS.IS 0.432742947264 AKENR.IS 0.411572932002 CIMSA.IS 0.409761734264 HALKB.IS 0.29317300613 ZOREN.IS 0.177975826959 AKSA.IS -0.164770083225 KARSN.IS -0.444213608009 TMSN.IS -1.12383635356 {'AFYON.IS': 0.2, 'BJKAS.IS': 0.2, 'EREGL.IS': 0.2, 'GOODY.IS': 0.2, 'KOZAL.IS': 0.2} Before Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 0.00000 0 19.45 0.00 0.00000 AFYON.IS 311005.58000 53133 5.46 290106.18 -20899.40000 BJKAS.IS 320653.02000 96366 3.47 334390.02 13737.00000 DOAS.IS 0.00000 0 10.60 0.00 0.00000 EREGL.IS 311758.90131 75315 4.06 305778.90 -5980.00131 GOODY.IS 3233.14670 66072 3.32 219359.04 216125.89330 KOZAL.IS 309625.45000 22583 12.73 287481.59 -22143.86000 weight symbol AEFES.IS 0.000000 AFYON.IS 0.201867 BJKAS.IS 0.232681 DOAS.IS 0.000000 EREGL.IS 0.212773 GOODY.IS 0.152638 KOZAL.IS 0.200041 Orders -------------------- action shares symbol time 0 sell 13535 BJKAS.IS 2016-06-30 1 sell 4521 EREGL.IS 2016-06-30 2 sell 4 KOZAL.IS 2016-06-30 3 sell 491 AFYON.IS 2016-06-30 4 buy 20501 GOODY.IS 2016-06-30 After Orders -------------------- cost shares current_price market_value profit \ symbol AEFES.IS 0.00000 0 19.45 0.00 0.00000 AFYON.IS 308103.77000 52642 5.46 287425.32 -20678.45000 BJKAS.IS 266715.82000 82831 3.47 287423.57 20707.75000 DOAS.IS 0.00000 0 10.60 0.00 0.00000 EREGL.IS 292085.36292 70794 4.06 287423.64 -4661.72292 GOODY.IS 71296.46670 86573 3.32 287422.36 216125.89330 KOZAL.IS 309575.29000 22579 12.73 287430.67 -22144.62000 weight symbol AEFES.IS 0.000000 AFYON.IS 0.200000 BJKAS.IS 0.199999 DOAS.IS 0.000000 EREGL.IS 0.199999 GOODY.IS 0.199998 KOZAL.IS 0.200004
/home/can/.local/lib/python2.7/site-packages/ipykernel/__main__.py:3: FutureWarning: how in .resample() is deprecated the new syntax is .resample(...).first() app.launch_new_instance()
summary(transactions, positions, trades)
***Transactions*** ---------------------------------------------------------------------- action commision price shares status symbol time 0 buy 1.999145 9.70930 2059 accepted DOAS.IS 2016-01-29 1 buy 1.999944 5.91000 3384 accepted AFYON.IS 2016-01-29 2 buy 1.999940 18.05000 1108 accepted AEFES.IS 2016-01-29 3 buy 1.998876 12.54000 1594 accepted KOZAL.IS 2016-01-29 4 buy 1.999999 0.04795 417101 accepted GOODY.IS 2016-01-29 5 buy 0.024204 10.08480 24 accepted DOAS.IS 2016-02-29 6 buy 0.077740 5.98000 130 accepted AFYON.IS 2016-02-29 7 buy 0.219042 16.98000 129 accepted AEFES.IS 2016-02-29 8 sell 0.485576 16.24000 299 accepted KOZAL.IS 2016-02-29 9 buy 0.163744 0.04646 35244 accepted GOODY.IS 2016-02-29 10 buy 0.356533 11.24710 317 accepted DOAS.IS 2016-03-31 11 buy 0.461188 6.37000 724 accepted AFYON.IS 2016-03-31 12 buy 0.080408 21.16000 38 accepted AEFES.IS 2016-03-31 13 buy 0.359593 18.07000 199 accepted KOZAL.IS 2016-03-31 14 sell 1.261192 0.08757 144021 accepted GOODY.IS 2016-03-31 15 buy 2.745270 5.17000 5310 accepted BJKAS.IS 2016-04-29 16 buy 2.745418 4.35159 6309 accepted EREGL.IS 2016-04-29 17 sell 2.769300 21.72000 1275 accepted AEFES.IS 2016-04-29 18 buy 0.010980 18.30000 6 accepted KOZAL.IS 2016-04-29 19 sell 2.899200 12.08000 2400 accepted DOAS.IS 2016-04-29 20 buy 0.138990 6.15000 226 accepted AFYON.IS 2016-04-29 21 buy 0.025743 0.08822 2918 accepted GOODY.IS 2016-04-29 22 buy 29.320032 3.22000 91056 accepted BJKAS.IS 2016-05-31 23 buy 28.430472 4.12000 69006 accepted EREGL.IS 2016-05-31 24 buy 28.968042 13.74000 21083 accepted KOZAL.IS 2016-05-31 25 buy 28.422696 5.84000 48669 accepted AFYON.IS 2016-05-31 26 sell 115.142865 4.69645 245170 accepted GOODY.IS 2016-05-31 27 sell 4.696645 3.47000 13535 accepted BJKAS.IS 2016-06-30 28 sell 1.835526 4.06000 4521 accepted EREGL.IS 2016-06-30 29 sell 0.005092 12.73000 4 accepted KOZAL.IS 2016-06-30 30 sell 0.268086 5.46000 491 accepted AFYON.IS 2016-06-30 31 buy 6.806332 3.32000 20501 accepted GOODY.IS 2016-06-30 ***Positions*** ---------------------------------------------------------------------- cost initial_shares price shares symbol time type 0 0.00000 2059 9.70930 0 DOAS.IS 2016-01-29 long 1 17097.63000 3384 5.91000 2893 AFYON.IS 2016-01-29 long 2 0.00000 1108 18.05000 0 AEFES.IS 2016-01-29 long 3 16189.14000 1594 12.54000 1291 KOZAL.IS 2016-01-29 long 4 1338.28450 417101 0.04795 27910 GOODY.IS 2016-01-29 long 5 0.00000 24 10.08480 0 DOAS.IS 2016-02-29 long 6 777.40000 130 5.98000 130 AFYON.IS 2016-02-29 long 7 0.00000 129 16.98000 0 AEFES.IS 2016-02-29 long 8 1637.43624 35244 0.04646 35244 GOODY.IS 2016-02-29 long 9 0.00000 317 11.24710 0 DOAS.IS 2016-03-31 long 10 4611.88000 724 6.37000 724 AFYON.IS 2016-03-31 long 11 0.00000 38 21.16000 0 AEFES.IS 2016-03-31 long 12 3595.93000 199 18.07000 199 KOZAL.IS 2016-03-31 long 13 0.00000 5310 5.17000 0 BJKAS.IS 2016-04-29 long 14 7780.64292 6309 4.35159 1788 EREGL.IS 2016-04-29 long 15 109.80000 6 18.30000 6 KOZAL.IS 2016-04-29 long 16 1389.90000 226 6.15000 226 AFYON.IS 2016-04-29 long 17 257.42596 2918 0.08822 2918 GOODY.IS 2016-04-29 long 18 266715.82000 91056 3.22000 82831 BJKAS.IS 2016-05-31 long 19 284304.72000 69006 4.12000 69006 EREGL.IS 2016-05-31 long 20 289680.42000 21083 13.74000 21083 KOZAL.IS 2016-05-31 long 21 284226.96000 48669 5.84000 48669 AFYON.IS 2016-05-31 long 22 68063.32000 20501 3.32000 20501 GOODY.IS 2016-06-30 long ***Trades*** ---------------------------------------------------------------------- buy_price profit sell_price shares symbol time 0 12.54000 1.106300e+03 16.24000 299 KOZAL.IS 2016-02-29 1 0.04795 5.706112e+03 0.08757 144021 GOODY.IS 2016-03-31 2 18.05000 4.066360e+03 21.72000 1108 AEFES.IS 2016-04-29 3 16.98000 6.114600e+02 21.72000 129 AEFES.IS 2016-04-29 4 21.16000 2.128000e+01 21.72000 38 AEFES.IS 2016-04-29 5 9.70930 4.881271e+03 12.08000 2059 DOAS.IS 2016-04-29 6 10.08480 4.788480e+01 12.08000 24 DOAS.IS 2016-04-29 7 11.24710 2.640293e+02 12.08000 317 DOAS.IS 2016-04-29 8 0.04795 1.139673e+06 4.69645 245170 GOODY.IS 2016-05-31 9 5.17000 -9.027000e+03 3.47000 5310 BJKAS.IS 2016-06-30 10 3.22000 2.056250e+03 3.47000 8225 BJKAS.IS 2016-06-30 11 4.35159 -1.318278e+03 4.06000 4521 EREGL.IS 2016-06-30 12 12.54000 7.600000e-01 12.73000 4 KOZAL.IS 2016-06-30 13 5.91000 -2.209500e+02 5.46000 491 AFYON.IS 2016-06-30
current_performance(portfolio, time = '2016-08-04')
portfolio
cost | shares | current_price | market_value | profit | weight | |
---|---|---|---|---|---|---|
symbol | ||||||
AEFES.IS | 0.00000 | 0 | 20.14 | 0.00 | 0.00000 | 0.000000 |
AFYON.IS | 308103.77000 | 52642 | 5.48 | 288478.16 | -19625.61000 | 0.190931 |
BJKAS.IS | 266715.82000 | 82831 | 4.25 | 352031.75 | 85315.93000 | 0.232994 |
DOAS.IS | 0.00000 | 0 | 10.29 | 0.00 | 0.00000 | 0.000000 |
EREGL.IS | 292085.36292 | 70794 | 4.67 | 330607.98 | 38522.61708 | 0.218815 |
GOODY.IS | 71296.46670 | 86573 | 3.58 | 309931.34 | 238634.87330 | 0.205130 |
KOZAL.IS | 309575.29000 | 22579 | 10.18 | 229854.22 | -79721.07000 | 0.152130 |
portfolio.market_value.sum()
1510903.45
paid_dividends(transactions, Dividends)
time | symbol | paid_dividend | |
---|---|---|---|
816 | 2016-04-07 | DOAS.IS | 3.272736e+03 |
1113 | 2016-05-25 | EREGL.IS | 1.892700e+03 |
1362 | 2016-05-25 | GOODY.IS | 1.720580e+06 |
dividends_and_splits.query("symbol == 'GOODY.IS'")
action | value | symbol | |
---|---|---|---|
2016-06-01 | SPLIT | 0.045455 | GOODY.IS |
2016-05-25 | DIVIDEND | 5.528110 | GOODY.IS |
2015-05-20 | DIVIDEND | 0.794024 | GOODY.IS |
2015-05-12 | DIVIDEND | 0.794024 | GOODY.IS |
2014-05-06 | DIVIDEND | 5.243630 | GOODY.IS |
2013-05-16 | DIVIDEND | 0.833000 | GOODY.IS |
2012-05-31 | DIVIDEND | 1.035160 | GOODY.IS |
2011-05-26 | DIVIDEND | 0.230000 | GOODY.IS |
temp = historical_performance(transactions, prices)
compare_with_benchmark(temp)
Algorithm performance: 1565.96392855 Benchmark performance: 5.60699416203
Initialization
Every month
# TODO: fill nan values
def momentum(price_data, start, end):
momentum_values = {symbol: (price_data[symbol].loc[end] - price_data[symbol].loc[start])
for symbol in price_data.columns if symbol != 'XU100.IS'}
return momentum_values
pd.date_range(start=running_points[0], periods=12, freq='BM')
DatetimeIndex(['2016-01-29', '2016-02-29', '2016-03-31', '2016-04-29', '2016-05-31', '2016-06-30', '2016-07-29', '2016-08-31', '2016-09-30', '2016-10-31', '2016-11-30', '2016-12-30'], dtype='datetime64[ns]', freq='BM')
portfolio, transactions, positions, trades = [], [], [], []
for t in running_points:
time = t.strftime("%Y-%m-%d")
if t in pd.date_range(start=running_points[0], periods=12, freq='BM'):
print t
print '-'*20
momentum_values = momentum(prices, t - pd.DateOffset(months=5) - 1*BDay(), t - 1*BDay())
for s in sorted(momentum_values, key=momentum_values.get, reverse=True):
print s, momentum_values[s]
n = 5
if len(portfolio) == 0:
new_weights = {s: 1./n for s in sorted(momentum_values, key=momentum_values.get, reverse=True)[:n]}
print new_weights
target_value = capital_base
rebalance_orders = rebalance(portfolio, new_weights, target_value, time)
else:
potentials = {key:value for key, value in momentum_values.iteritems() if key not in portfolio.index }
new_weights = {}
for symbol in portfolio.index:
if portfolio["market_value"].loc[symbol]:
if momentum_values[symbol] < 0:
s = sorted(potentials, key=potentials.get, reverse=True)[0]
print symbol + "out" + s + "in"
new_weights[s] = 1./n
del potentials[s]
else:
new_weights[symbol] = 1./n
current_performance(portfolio, time)
print new_weights
rebalance_orders = rebalance(portfolio, new_weights, None, time)
print "Before Orders"
print "-"*20
print portfolio["market_value"].sum() if len(portfolio) else 0
print portfolio
print " "
print "Orders"
print "-"*20
print pd.DataFrame(rebalance_orders)
print " "
print sum([order["shares"]*get_price(order["symbol"], time) for order in rebalance_orders if order["action"]=="buy"])
print sum([order["shares"]*get_price(order["symbol"], time) for order in rebalance_orders if order["action"]=="sell"])
execute_orders(rebalance_orders, transactions, positions, trades)
portfolio = calculate_portfolio(positions)
current_performance(portfolio, time)
print "After Orders"
print "-"*20
print portfolio
print portfolio["market_value"].sum()
print " "
portfolio = calculate_portfolio(positions)
2016-01-29 00:00:00 -------------------- TMSN.IS 4.5 FROTO.IS 2.4809 BJKAS.IS 1.02 PETKM.IS 0.83363 AFYON.IS 0.61 ALARK.IS 0.54994 ULKER.IS 0.39 ZOREN.IS 0.23881 AKBNK.IS 0.14716 SISE.IS 0.10687 YKBNK.IS 0.06 VAKFN.IS 0.0523 GARAN.IS 0.039 KARSN.IS 0.03 GOODY.IS 0.00778 AKSA.IS 0.0 AKENR.IS -0.01 TRKCM.IS -0.04577 VAKBN.IS -0.05946 TKFEN.IS -0.11 CIMSA.IS -0.6547 MGROS.IS -0.7 THYAO.IS -0.73 EREGL.IS -0.76409 HALKB.IS -0.79 TCELL.IS -1.23 DOAS.IS -1.7434 AEFES.IS -2.81 KOZAL.IS -12.3 {'AFYON.IS': 0.2, 'TMSN.IS': 0.2, 'BJKAS.IS': 0.2, 'FROTO.IS': 0.2, 'PETKM.IS': 0.2} Before Orders -------------------- 0 [] Orders -------------------- action shares symbol time 0 buy 3384 AFYON.IS 2016-01-29 1 buy 1901 TMSN.IS 2016-01-29 2 buy 6734 BJKAS.IS 2016-01-29 3 buy 636 FROTO.IS 2016-01-29 4 buy 6250 PETKM.IS 2016-01-29 99982.3716 0 After Orders -------------------- cost shares current_price market_value profit weight symbol AFYON.IS 19999.4400 3384 5.91000 19999.4400 0.0 0.200030 BJKAS.IS 19999.9800 6734 2.97000 19999.9800 0.0 0.200035 FROTO.IS 19986.6816 636 31.42560 19986.6816 0.0 0.199902 PETKM.IS 19997.7500 6250 3.19964 19997.7500 0.0 0.200013 TMSN.IS 19998.5200 1901 10.52000 19998.5200 0.0 0.200020 99982.3716 2016-02-29 00:00:00 -------------------- TMSN.IS 3.55 BJKAS.IS 2.69 FROTO.IS 2.5783 DOAS.IS 0.9924 AKBNK.IS 0.80449 AFYON.IS 0.8 PETKM.IS 0.73861 CIMSA.IS 0.47284 SISE.IS 0.47201 GARAN.IS 0.443 ZOREN.IS 0.33625 YKBNK.IS 0.29 VAKBN.IS 0.2081 TCELL.IS 0.19 VAKFN.IS 0.1046 KARSN.IS 0.05 GOODY.IS 0.00748 AKENR.IS -0.04 AKSA.IS -0.04601 TKFEN.IS -0.05 TRKCM.IS -0.05492 ALARK.IS -0.07457 HALKB.IS -0.12 EREGL.IS -0.32613 ULKER.IS -0.34 THYAO.IS -0.8 MGROS.IS -1.32 AEFES.IS -4.3 KOZAL.IS -6.08 {'AFYON.IS': 0.2, 'BJKAS.IS': 0.2, 'TMSN.IS': 0.2, 'FROTO.IS': 0.2, 'PETKM.IS': 0.2} Before Orders -------------------- 112051.4147 cost shares current_price market_value profit \ symbol AFYON.IS 19999.4400 3384 5.98000 20236.3200 236.8800 BJKAS.IS 19999.9800 6734 4.68000 31515.1200 11515.1400 FROTO.IS 19986.6816 636 33.95520 21595.5072 1608.8256 PETKM.IS 19997.7500 6250 3.21803 20112.6875 114.9375 TMSN.IS 19998.5200 1901 9.78000 18591.7800 -1406.7400 weight symbol AFYON.IS 0.180599 BJKAS.IS 0.281256 FROTO.IS 0.192729 PETKM.IS 0.179495 TMSN.IS 0.165922 Orders -------------------- action shares symbol time 0 buy 363 AFYON.IS 2016-02-29 1 sell 1945 BJKAS.IS 2016-02-29 2 buy 390 TMSN.IS 2016-02-29 3 buy 23 FROTO.IS 2016-02-29 4 buy 713 PETKM.IS 2016-02-29 9060.36499 9102.6 After Orders -------------------- cost shares current_price market_value profit \ symbol AFYON.IS 22170.18000 3747 5.98000 22407.06000 236.8800 BJKAS.IS 14223.33000 4789 4.68000 22412.52000 8189.1900 FROTO.IS 20767.65120 659 33.95520 22376.47680 1608.8256 PETKM.IS 22292.20539 6963 3.21803 22407.14289 114.9375 TMSN.IS 23812.72000 2291 9.78000 22405.98000 -1406.7400 weight symbol AFYON.IS 0.200047 BJKAS.IS 0.200095 FROTO.IS 0.199774 PETKM.IS 0.200047 TMSN.IS 0.200037 112009.17969 2016-03-31 00:00:00 -------------------- FROTO.IS 2.8993 BJKAS.IS 2.89 TMSN.IS 1.89 KOZAL.IS 1.75 DOAS.IS 1.5914 ULKER.IS 1.52 TKFEN.IS 1.15 CIMSA.IS 1.04194 PETKM.IS 0.95009 AKBNK.IS 0.65168 YKBNK.IS 0.6 GARAN.IS 0.531 VAKBN.IS 0.50541 MGROS.IS 0.43 ZOREN.IS 0.33518 VAKFN.IS 0.3138 ALARK.IS 0.29827 SISE.IS 0.29389 AFYON.IS 0.2 EREGL.IS 0.13045 TRKCM.IS 0.10069 KARSN.IS 0.05 GOODY.IS 0.02904 AKENR.IS 0.02 TCELL.IS -0.03 AKSA.IS -0.22085 HALKB.IS -0.58 THYAO.IS -0.84 AEFES.IS -1.91 {'AFYON.IS': 0.2, 'BJKAS.IS': 0.2, 'TMSN.IS': 0.2, 'FROTO.IS': 0.2, 'PETKM.IS': 0.2} Before Orders -------------------- 117341.42468 cost shares current_price market_value profit \ symbol AFYON.IS 22170.18000 3747 6.37000 23868.39000 1698.21000 BJKAS.IS 14223.33000 4789 5.05000 24184.45000 9961.12000 FROTO.IS 20767.65120 659 36.13460 23812.70140 3045.05020 PETKM.IS 22292.20539 6963 3.66856 25544.18328 3251.97789 TMSN.IS 23812.72000 2291 8.70000 19931.70000 -3881.02000 weight symbol AFYON.IS 0.203410 BJKAS.IS 0.206103 FROTO.IS 0.202935 PETKM.IS 0.217691 TMSN.IS 0.169861 Orders -------------------- action shares symbol time 0 sell 62 AFYON.IS 2016-03-31 1 sell 141 BJKAS.IS 2016-03-31 2 buy 406 TMSN.IS 2016-03-31 3 sell 9 FROTO.IS 2016-03-31 4 sell 565 PETKM.IS 2016-03-31 3532.2 3504.9378 After Orders -------------------- cost shares current_price market_value profit \ symbol AFYON.IS 21803.76000 3685 6.37000 23473.45000 1669.69000 BJKAS.IS 13804.56000 4648 5.05000 23472.40000 9667.84000 FROTO.IS 20484.82080 650 36.13460 23487.49000 3002.66920 PETKM.IS 20484.40879 6398 3.66856 23471.44688 2987.03809 TMSN.IS 27344.92000 2697 8.70000 23463.90000 -3881.02000 weight symbol AFYON.IS 0.199998 BJKAS.IS 0.199989 FROTO.IS 0.200117 PETKM.IS 0.199980 TMSN.IS 0.199916 117368.68688 2016-04-29 00:00:00 -------------------- FROTO.IS 7.1323 KOZAL.IS 6.37 ULKER.IS 3.45 BJKAS.IS 2.94 AKBNK.IS 1.85052 TKFEN.IS 1.85 CIMSA.IS 1.7974 DOAS.IS 1.7132 MGROS.IS 1.49 GARAN.IS 1.387 PETKM.IS 1.15236 AEFES.IS 1.06 VAKBN.IS 0.93154 EREGL.IS 0.91318 YKBNK.IS 0.87 SISE.IS 0.81044 ALARK.IS 0.77365 TCELL.IS 0.68 TRKCM.IS 0.42106 VAKFN.IS 0.38851 AKENR.IS 0.34 ZOREN.IS 0.34 GOODY.IS 0.04098 HALKB.IS -0.02 KARSN.IS -0.11 AKSA.IS -0.28606 AFYON.IS -0.39 TMSN.IS -0.45 THYAO.IS -0.84 AFYON.ISoutKOZAL.ISin TMSN.ISoutULKER.ISin {'KOZAL.IS': 0.2, 'ULKER.IS': 0.2, 'BJKAS.IS': 0.2, 'FROTO.IS': 0.2, 'PETKM.IS': 0.2} Before Orders -------------------- 117236.85822 cost shares current_price market_value profit \ symbol AFYON.IS 21803.76000 3685 6.15000 22662.75000 858.99000 BJKAS.IS 13804.56000 4648 5.17000 24030.16000 10225.60000 FROTO.IS 20484.82080 650 37.60000 24440.00000 3955.17920 PETKM.IS 20484.40879 6398 3.77889 24177.33822 3692.92943 TMSN.IS 27344.92000 2697 8.13000 21926.61000 -5418.31000 weight symbol AFYON.IS 0.193307 BJKAS.IS 0.204971 FROTO.IS 0.208467 PETKM.IS 0.206226 TMSN.IS 0.187028 Orders -------------------- action shares symbol time 0 sell 112 BJKAS.IS 2016-04-29 1 buy 1281 KOZAL.IS 2016-04-29 2 sell 26 FROTO.IS 2016-04-29 3 buy 1052 ULKER.IS 2016-04-29 4 sell 3685 AFYON.IS 2016-04-29 5 sell 2697 TMSN.IS 2016-04-29 6 sell 193 PETKM.IS 2016-04-29 46880.86 46875.32577 After Orders -------------------- cost shares current_price market_value profit \ symbol AFYON.IS 0.00000 0 6.15000 0.00000 0.00000 BJKAS.IS 13471.92000 4536 5.17000 23451.12000 9979.20000 FROTO.IS 19667.75520 624 37.60000 23462.40000 3794.64480 KOZAL.IS 23442.30000 1281 18.30000 23442.30000 0.00000 PETKM.IS 19866.87827 6205 3.77889 23448.01245 3581.13418 TMSN.IS 0.00000 0 8.13000 0.00000 0.00000 ULKER.IS 23438.56000 1052 22.28000 23438.56000 0.00000 weight symbol AFYON.IS 0.000000 BJKAS.IS 0.200023 FROTO.IS 0.200119 KOZAL.IS 0.199947 PETKM.IS 0.199996 TMSN.IS 0.000000 ULKER.IS 0.199915 117242.39245 2016-05-31 00:00:00 -------------------- FROTO.IS 4.6484 GOODY.IS 4.64283 ULKER.IS 3.28 TKFEN.IS 3.2 CIMSA.IS 2.03478 EREGL.IS 1.24341 DOAS.IS 1.2062 AKBNK.IS 1.20108 KOZAL.IS 1.16 PETKM.IS 1.10639 BJKAS.IS 1.04 YKBNK.IS 0.77 ALARK.IS 0.60587 VAKBN.IS 0.54504 TCELL.IS 0.53 GARAN.IS 0.446 TRKCM.IS 0.44164 SISE.IS 0.42748 VAKFN.IS 0.38104 AKENR.IS 0.14 ZOREN.IS -0.07 AEFES.IS -0.08 AFYON.IS -0.23 KARSN.IS -0.37 MGROS.IS -0.48 THYAO.IS -1.05 TMSN.IS -1.17 AKSA.IS -1.22878 HALKB.IS -1.47 {'KOZAL.IS': 0.2, 'BJKAS.IS': 0.2, 'ULKER.IS': 0.2, 'FROTO.IS': 0.2, 'PETKM.IS': 0.2} Before Orders -------------------- 100730.78005 cost shares current_price market_value profit \ symbol AFYON.IS 0.00000 0 5.84000 0.00000 0.00000 BJKAS.IS 13471.92000 4536 3.22000 14605.92000 1134.00000 FROTO.IS 19667.75520 624 34.98000 21827.52000 2159.76480 KOZAL.IS 23442.30000 1281 13.74000 17600.94000 -5841.36000 PETKM.IS 19866.87827 6205 3.90761 24246.72005 4379.84178 TMSN.IS 0.00000 0 7.72000 0.00000 0.00000 ULKER.IS 23438.56000 1052 21.34000 22449.68000 -988.88000 weight symbol AFYON.IS 0.000000 BJKAS.IS 0.145000 FROTO.IS 0.216692 KOZAL.IS 0.174732 PETKM.IS 0.240708 TMSN.IS 0.000000 ULKER.IS 0.222868 Orders -------------------- action shares symbol time 0 buy 1720 BJKAS.IS 2016-05-31 1 buy 185 KOZAL.IS 2016-05-31 2 sell 48 FROTO.IS 2016-05-31 3 sell 107 ULKER.IS 2016-05-31 4 sell 1049 PETKM.IS 2016-05-31 8080.3 8061.50289 After Orders -------------------- cost shares current_price market_value profit \ symbol AFYON.IS 0.00000 0 5.84000 0.00000 0.00000 BJKAS.IS 19010.32000 6256 3.22000 20144.32000 1134.00000 FROTO.IS 18159.32640 576 34.98000 20148.48000 1989.15360 KOZAL.IS 25984.20000 1466 13.74000 20142.84000 -5841.36000 PETKM.IS 16510.45591 5156 3.90761 20147.63716 3637.18125 TMSN.IS 0.00000 0 7.72000 0.00000 0.00000 ULKER.IS 21054.60000 945 21.34000 20166.30000 -888.30000 weight symbol AFYON.IS 0.000000 BJKAS.IS 0.199944 FROTO.IS 0.199986 KOZAL.IS 0.199930 PETKM.IS 0.199977 TMSN.IS 0.000000 ULKER.IS 0.200163 100749.57716 2016-06-30 00:00:00 -------------------- TKFEN.IS 4.16 GOODY.IS 3.30205 CIMSA.IS 2.115 ULKER.IS 2.08 EREGL.IS 1.23068 AKBNK.IS 1.086 DOAS.IS 1.0207 VAKBN.IS 0.80396 PETKM.IS 0.62036 SISE.IS 0.5996 AEFES.IS 0.59 TRKCM.IS 0.58905 KOZAL.IS 0.45 BJKAS.IS 0.43 MGROS.IS 0.37 VAKFN.IS 0.33839 GARAN.IS 0.289 TCELL.IS 0.24 FROTO.IS 0.2344 YKBNK.IS 0.22 ZOREN.IS 0.15 AKENR.IS 0.04 ALARK.IS -0.06358 KARSN.IS -0.36 AFYON.IS -0.43 HALKB.IS -1.4 THYAO.IS -1.5 AKSA.IS -1.70033 TMSN.IS -3.14 {'KOZAL.IS': 0.2, 'BJKAS.IS': 0.2, 'ULKER.IS': 0.2, 'FROTO.IS': 0.2, 'PETKM.IS': 0.2} Before Orders -------------------- 97640.14 cost shares current_price market_value profit \ symbol AFYON.IS 0.00000 0 5.46 0.00 0.00000 BJKAS.IS 19010.32000 6256 3.47 21708.32 2698.00000 FROTO.IS 18159.32640 576 30.60 17625.60 -533.72640 KOZAL.IS 25984.20000 1466 12.73 18662.18 -7322.02000 PETKM.IS 16510.45591 5156 3.84 19799.04 3288.58409 TMSN.IS 0.00000 0 7.40 0.00 0.00000 ULKER.IS 21054.60000 945 21.00 19845.00 -1209.60000 weight symbol AFYON.IS 0.000000 BJKAS.IS 0.222330 FROTO.IS 0.180516 KOZAL.IS 0.191132 PETKM.IS 0.202776 TMSN.IS 0.000000 ULKER.IS 0.203246 Orders -------------------- action shares symbol time 0 sell 628 BJKAS.IS 2016-06-30 1 buy 68 KOZAL.IS 2016-06-30 2 buy 62 FROTO.IS 2016-06-30 3 sell 15 ULKER.IS 2016-06-30 4 sell 70 PETKM.IS 2016-06-30 2762.84 2762.96 After Orders -------------------- cost shares current_price market_value profit \ symbol AFYON.IS 0.00000 0 5.46 0.00 0.00000 BJKAS.IS 17145.16000 5628 3.47 19529.16 2384.00000 FROTO.IS 20056.52640 638 30.60 19522.80 -533.72640 KOZAL.IS 26849.84000 1534 12.73 19527.82 -7322.02000 PETKM.IS 16286.48111 5086 3.84 19530.24 3243.75889 TMSN.IS 0.00000 0 7.40 0.00 0.00000 ULKER.IS 20720.40000 930 21.00 19530.00 -1190.40000 weight symbol AFYON.IS 0.000000 BJKAS.IS 0.200012 FROTO.IS 0.199947 KOZAL.IS 0.199998 PETKM.IS 0.200023 TMSN.IS 0.000000 ULKER.IS 0.200020 97640.02
summary(transactions, positions, trades)
***Transactions*** ---------------------------------------------------------------------- action commision price shares status symbol time 0 buy 1.999944 5.91000 3384 accepted AFYON.IS 2016-01-29 1 buy 1.999852 10.52000 1901 accepted TMSN.IS 2016-01-29 2 buy 1.999998 2.97000 6734 accepted BJKAS.IS 2016-01-29 3 buy 1.998668 31.42560 636 accepted FROTO.IS 2016-01-29 4 buy 1.999775 3.19964 6250 accepted PETKM.IS 2016-01-29 5 buy 0.217074 5.98000 363 accepted AFYON.IS 2016-02-29 6 sell 0.910260 4.68000 1945 accepted BJKAS.IS 2016-02-29 7 buy 0.381420 9.78000 390 accepted TMSN.IS 2016-02-29 8 buy 0.078097 33.95520 23 accepted FROTO.IS 2016-02-29 9 buy 0.229446 3.21803 713 accepted PETKM.IS 2016-02-29 10 sell 0.039494 6.37000 62 accepted AFYON.IS 2016-03-31 11 sell 0.071205 5.05000 141 accepted BJKAS.IS 2016-03-31 12 buy 0.353220 8.70000 406 accepted TMSN.IS 2016-03-31 13 sell 0.032521 36.13460 9 accepted FROTO.IS 2016-03-31 14 sell 0.207274 3.66856 565 accepted PETKM.IS 2016-03-31 15 sell 0.057904 5.17000 112 accepted BJKAS.IS 2016-04-29 16 buy 2.344230 18.30000 1281 accepted KOZAL.IS 2016-04-29 17 sell 0.097760 37.60000 26 accepted FROTO.IS 2016-04-29 18 buy 2.343856 22.28000 1052 accepted ULKER.IS 2016-04-29 19 sell 2.266275 6.15000 3685 accepted AFYON.IS 2016-04-29 20 sell 2.192661 8.13000 2697 accepted TMSN.IS 2016-04-29 21 sell 0.072933 3.77889 193 accepted PETKM.IS 2016-04-29 22 buy 0.553840 3.22000 1720 accepted BJKAS.IS 2016-05-31 23 buy 0.254190 13.74000 185 accepted KOZAL.IS 2016-05-31 24 sell 0.167904 34.98000 48 accepted FROTO.IS 2016-05-31 25 sell 0.228338 21.34000 107 accepted ULKER.IS 2016-05-31 26 sell 0.409908 3.90761 1049 accepted PETKM.IS 2016-05-31 27 sell 0.217916 3.47000 628 accepted BJKAS.IS 2016-06-30 28 buy 0.086564 12.73000 68 accepted KOZAL.IS 2016-06-30 29 buy 0.189720 30.60000 62 accepted FROTO.IS 2016-06-30 30 sell 0.031500 21.00000 15 accepted ULKER.IS 2016-06-30 31 sell 0.026880 3.84000 70 accepted PETKM.IS 2016-06-30 ***Positions*** ---------------------------------------------------------------------- cost initial_shares price shares symbol time type 0 0.00000 3384 5.91000 0 AFYON.IS 2016-01-29 long 1 0.00000 1901 10.52000 0 TMSN.IS 2016-01-29 long 2 11606.76000 6734 2.97000 3908 BJKAS.IS 2016-01-29 long 3 17378.35680 636 31.42560 553 FROTO.IS 2016-01-29 long 4 13992.02572 6250 3.19964 4373 PETKM.IS 2016-01-29 long 5 0.00000 363 5.98000 0 AFYON.IS 2016-02-29 long 6 0.00000 390 9.78000 0 TMSN.IS 2016-02-29 long 7 780.96960 23 33.95520 23 FROTO.IS 2016-02-29 long 8 2294.45539 713 3.21803 713 PETKM.IS 2016-02-29 long 9 0.00000 406 8.70000 0 TMSN.IS 2016-03-31 long 10 23442.30000 1281 18.30000 1281 KOZAL.IS 2016-04-29 long 11 20720.40000 1052 22.28000 930 ULKER.IS 2016-04-29 long 12 5538.40000 1720 3.22000 1720 BJKAS.IS 2016-05-31 long 13 2541.90000 185 13.74000 185 KOZAL.IS 2016-05-31 long 14 865.64000 68 12.73000 68 KOZAL.IS 2016-06-30 long 15 1897.20000 62 30.60000 62 FROTO.IS 2016-06-30 long ***Trades*** ---------------------------------------------------------------------- buy_price profit sell_price shares symbol time 0 2.97000 3325.95000 4.68000 1945 BJKAS.IS 2016-02-29 1 5.91000 28.52000 6.37000 62 AFYON.IS 2016-03-31 2 2.97000 293.28000 5.05000 141 BJKAS.IS 2016-03-31 3 31.42560 42.38100 36.13460 9 FROTO.IS 2016-03-31 4 3.19964 264.93980 3.66856 565 PETKM.IS 2016-03-31 5 2.97000 246.40000 5.17000 112 BJKAS.IS 2016-04-29 6 31.42560 160.53440 37.60000 26 FROTO.IS 2016-04-29 7 5.91000 797.28000 6.15000 3322 AFYON.IS 2016-04-29 8 5.98000 61.71000 6.15000 363 AFYON.IS 2016-04-29 9 10.52000 -4543.39000 8.13000 1901 TMSN.IS 2016-04-29 10 9.78000 -643.50000 8.13000 390 TMSN.IS 2016-04-29 11 8.70000 -231.42000 8.13000 406 TMSN.IS 2016-04-29 12 3.19964 111.79525 3.77889 193 PETKM.IS 2016-04-29 13 31.42560 170.61120 34.98000 48 FROTO.IS 2016-05-31 14 22.28000 -100.58000 21.34000 107 ULKER.IS 2016-05-31 15 3.19964 742.66053 3.90761 1049 PETKM.IS 2016-05-31 16 2.97000 314.00000 3.47000 628 BJKAS.IS 2016-06-30 17 22.28000 -19.20000 21.00000 15 ULKER.IS 2016-06-30 18 3.19964 44.82520 3.84000 70 PETKM.IS 2016-06-30
current_performance(portfolio, time = '2016-07-18')
portfolio
cost | shares | current_price | market_value | profit | weight | |
---|---|---|---|---|---|---|
symbol | ||||||
AFYON.IS | 0.00000 | 0 | 5.14 | 0.00 | 0.00000 | 0.000000 |
BJKAS.IS | 17145.16000 | 5628 | 3.90 | 21949.20 | 4804.04000 | 0.222960 |
FROTO.IS | 20056.52640 | 638 | 32.32 | 20620.16 | 563.63360 | 0.209459 |
KOZAL.IS | 26849.84000 | 1534 | 10.63 | 16306.42 | -10543.42000 | 0.165641 |
PETKM.IS | 16286.48111 | 5086 | 3.94 | 20038.84 | 3752.35889 | 0.203554 |
TMSN.IS | 0.00000 | 0 | 7.10 | 0.00 | 0.00000 | 0.000000 |
ULKER.IS | 20720.40000 | 930 | 21.00 | 19530.00 | -1190.40000 | 0.198386 |
portfolio["market_value"].sum()
98444.62
paid_dividends(transactions, Dividends)
time | symbol | paid_dividend | |
---|---|---|---|
564 | 2016-04-04 | FROTO.IS | 650.00 |
1146 | 2016-06-27 | PETKM.IS | 1624.14 |
temp = historical_performance(transactions, prices)
compare_with_benchmark(temp)
Algorithm performance: 13.1896335214 Benchmark performance: 5.60699416203
We can withdraw / deposit money into the portfolio or while rebalancing some amount of free cash can left. In this kind of situations it is hard to calculate the performance of a portfolio. To overcome this situation one way is to calculate an index value and to calculate performance over this index value instead of market value.
historical_performance(pd.DataFrame(transactions)[0:5].to_dict("records"), prices)["2016-02-25":"2016-03-02"]
Date 2016-02-25 113231.4596 2016-02-26 111634.3921 2016-02-29 112051.4147 2016-03-01 113060.0381 2016-03-02 113371.5324 dtype: float64
historical_performance(transactions, prices)["2016-02-25":"2016-03-02"]
Date 2016-02-25 113231.45960 2016-02-26 111634.39210 2016-02-29 112009.17969 2016-03-01 112774.81843 2016-03-02 112975.15510 dtype: float64
pd.pivot_table(pd.DataFrame(transactions), values="shares", index="time", columns="symbol")
symbol | AFYON.IS | BJKAS.IS | FROTO.IS | KOZAL.IS | PETKM.IS | TMSN.IS | ULKER.IS |
---|---|---|---|---|---|---|---|
time | |||||||
2016-01-29 | 3384.0 | 6734.0 | 636.0 | NaN | 6250.0 | 1901.0 | NaN |
2016-02-29 | 363.0 | 1945.0 | 23.0 | NaN | 713.0 | 390.0 | NaN |
2016-03-31 | 62.0 | 141.0 | 9.0 | NaN | 565.0 | 406.0 | NaN |
2016-04-29 | 3685.0 | 112.0 | 26.0 | 1281.0 | 193.0 | 2697.0 | 1052.0 |
2016-05-31 | NaN | 1720.0 | 48.0 | 185.0 | 1049.0 | NaN | 107.0 |
2016-06-30 | NaN | 628.0 | 62.0 | 68.0 | 70.0 | NaN | 15.0 |
The value-at-risk is a measure of how much money can be lost for a period of time. Of course there is a (very small) probability that we can lost all our money. We can talk about the distrubition of the money that we can lost. For the value-at-risk we choose a probability say 99% and say that we will not loose money more then $ x $ with probability 99%.
There can be different methods to estimate the risk:
One way of chosing a methods is to test against historical data which is called backtesting.
from matplotlib.dates import AutoDateLocator
from matplotlib.ticker import MultipleLocator
# Historical method
returns = historical_performance(transactions, prices).pct_change().dropna()
returns.hist(bins=50, figsize=(15,10))
var_historic = returns.quantile(q = 0.01)
var_historic
-0.072105940035707305
# The Variance-Covariance Method
mu = np.mean(returns)
sigma = np.std(returns)
var_parametric = st.norm.ppf(0.01) * sigma
var_parametric
-0.079391854933226536
# Monte Carlo Simulation
samples = np.random.normal(mu, sigma, 100)
var_montecarlo = np.percentile(samples, 0.01)
var_montecarlo
-0.09693688460895461
ax = returns.plot(kind='bar', title ="V comp",figsize=(15,10),legend=True, fontsize=12)
ax.set_xlabel("Hour",fontsize=12)
AutoDateLocator()
loc = MultipleLocator(base=10.0)
ax.xaxis.set_major_locator(loc)
ax.set_ylabel("V",fontsize=12)
plt.axhline(y=var_historic, color='r', linestyle='-')
plt.axhline(y=var_parametric, color='r', linestyle='-')
plt.axhline(y=var_montecarlo, color='r', linestyle='-')
plt.show()
The risk profile is a way of categorizing portfolios according their risk. Risk profile of a portfolio depends on its yearly volatility. The yearly volatily is calculated by multiplying the standard deviation of weekly returns by square root of 52 (number of weeks in a year).
Cutoff points for yearly volatility is: [0, 0.5, 2, 5, 10, 15, 25]
historical_performance(transactions, prices).pct_change().resample("W-MON", label="left" ,closed="left").sum().plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7fc0b029c5d0>
historical_performance(transactions, prices).pct_change().resample("W-MON", label="left" ,closed="left").sum().cumsum().plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7fc0aae3dfd0>
def calculate_risk_value(historical_prices):
return np.std((historical_prices.pct_change() + 1).resample("W-MON", label="left" ,closed="left").prod() - 1) * sqrt(52)
risk_value = calculate_risk_value(historical_performance(transactions, prices)) * 100
from bisect import bisect
RiskLevels = [0, 0.5, 2, 5, 10, 15, 25]
bisect(RiskLevels, risk_value)
7
#sparkline
historical_prices = historical_performance(transactions, prices)
weekly_returns = ((historical_prices.pct_change() + 1).resample("W-MON", label="left" ,closed="left").prod() - 1)
plt.plot(weekly_returns)
plt.axis("off");
plt.savefig("trend.png")