Skip to content

Commit

Permalink
better charts
Browse files Browse the repository at this point in the history
  • Loading branch information
timkpaine committed Jun 1, 2019
1 parent 0cd102b commit 801a9cb
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 53 deletions.
59 changes: 36 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,57 +277,70 @@ We should see the following output:
This will call our `onAnalyze` function, which in this case is implemented to plot some performance characteristics with `matplotlib`.

```python3
def onAnalyze(self, engine) -> None:
import pandas
import matplotlib.pyplot as plt
import numpy as np
import matplotlib, matplotlib.pyplot as plt
import seaborn as sns
matplotlib.rc('font', **{'size': 5})

# extract data from trading engine
portfolio_value = engine.portfolio_value()
requests = engine.query().query_tradereqs()
responses = engine.query().query_traderesps()
trades = pandas.DataFrame([{'time': x.time, 'price': x.price} for x in engine.query().query_trades(instrument=requests[0].instrument, page=None)])
trades.set_index(['time'], inplace=True)

pd = pandas.DataFrame(portfolio_value, columns=['time', 'value'])
# format into pandas
pd = pandas.DataFrame(portfolio_value, columns=['time', 'value', 'pnl'])
pd.set_index(['time'], inplace=True)

# setup charting
sns.set_style('darkgrid')
fig = plt.figure(figsize=(5, 8))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)

plt.title('BTC algo 1 performance')
ax1.plot(pd)

fig = plt.figure()
ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(312)
ax3 = fig.add_subplot(313)

# plot algo performance
pd.plot(ax=ax1, y=['value'], legend=False, fontsize=5, rot=0)

# plot up/down chart
pd['pos'] = pd['pnl']
pd['neg'] = pd['pnl']
pd['pos'][pd['pos'] <= 0] = np.nan
pd['neg'][pd['neg'] > 0] = np.nan
pd.plot(ax=ax2, y=['pos', 'neg'], kind='area', stacked=False, color=['green', 'red'], legend=False, linewidth=0, fontsize=5, rot=0)

# annotate with key data
ax1.set_title('Performance')
ax1.set_ylabel('Portfolio value($)')
for xy in [portfolio_value[0]] + [portfolio_value[-1]]:
for xy in [portfolio_value[0][:2]] + [portfolio_value[-1][:2]]:
ax1.annotate('$%s' % xy[1], xy=xy, textcoords='data')
ax2.annotate('$%s' % xy[1], xy=xy, textcoords='data')
ax3.annotate('$%s' % xy[1], xy=xy, textcoords='data')

ax2.set_title('Trades')
ax2.set_ylabel('Intent/Action')
ax2.set_xlabel('Date')
# plot trade intent/trade action
ax3.set_ylabel('Intent/Action')
ax3.set_xlabel('Date')

ax2.plot([x.time for x in requests if x.side == Side.BUY],
ax3.plot(trades)
ax3.plot([x.time for x in requests if x.side == Side.BUY],
[x.price for x in requests if x.side == Side.BUY],
'2', color='y')
ax2.plot([x.time for x in requests if x.side == Side.SELL],
ax3.plot([x.time for x in requests if x.side == Side.SELL],
[x.price for x in requests if x.side == Side.SELL],
'1', color='y')
ax2.plot([x.time for x in responses if x.side == Side.BUY], # FIXME
ax3.plot([x.time for x in responses if x.side == Side.BUY], # FIXME
[x.price for x in responses if x.side == Side.BUY],
'^', color='g')
ax2.plot([x.time for x in responses if x.side == Side.SELL], # FIXME
ax3.plot([x.time for x in responses if x.side == Side.SELL], # FIXME
[x.price for x in responses if x.side == Side.SELL],
'v', color='r')
ax2.plot(trades)

# set same limits
y_bot, y_top = ax1.get_ylim()
x_bot, x_top = ax1.get_xlim()
ax2.set_ylim(y_bot, y_top)
ax2.set_xlim(x_bot, x_top)

ax3.set_ylim(y_bot, y_top)
ax3.set_xlim(x_bot, x_top)
plt.show()
```

Expand Down
4 changes: 2 additions & 2 deletions aat/strategies/backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def onAnalyze(self, engine) -> None:
trades = pandas.DataFrame([{'time': x.time, 'price': x.price} for x in engine.query().query_trades(instrument=requests[0].instrument, page=None)])
trades.set_index(['time'], inplace=True)

pd = pandas.DataFrame(portfolio_value, columns=['time', 'value'])
pd = pandas.DataFrame(portfolio_value, columns=['time', 'value', 'pnl'])
pd.set_index(['time'], inplace=True)

print(self.size, pd.iloc[1].value, pd.iloc[-1].value)
Expand All @@ -113,7 +113,7 @@ def onAnalyze(self, engine) -> None:
fig, ax1 = plt.subplots()

# plt.title('BTC algo 1 performance - %d-%d Momentum ' % (self.short, self.long))
ax1.plot(pd)
ax1.plot(pd, secondary_y=['pnl'])

ax1.set_ylabel('Portfolio value($)')
ax1.set_xlabel('Date')
Expand Down
61 changes: 36 additions & 25 deletions aat/strategies/buy_and_hold.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,60 +35,71 @@ def onError(self, e) -> None:

def onAnalyze(self, engine) -> None:
import pandas
import matplotlib.pyplot as plt
import numpy as np
import matplotlib, matplotlib.pyplot as plt
import seaborn as sns
matplotlib.rc('font', **{'size': 5})

# extract data from trading engine
portfolio_value = engine.portfolio_value()
requests = engine.query().query_tradereqs()
responses = engine.query().query_traderesps()
trades = pandas.DataFrame([{'time': x.time, 'price': x.price} for x in engine.query().query_trades(instrument=requests[0].instrument, page=None)])
trades.set_index(['time'], inplace=True)

pd = pandas.DataFrame(portfolio_value, columns=['time', 'value'])
# format into pandas
pd = pandas.DataFrame(portfolio_value, columns=['time', 'value', 'pnl'])
pd.set_index(['time'], inplace=True)

# setup charting
sns.set_style('darkgrid')
fig = plt.figure(figsize=(5, 8))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)

plt.title('BTC algo 1 performance')
ax1.plot(pd)

fig = plt.figure()
ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(312)
ax3 = fig.add_subplot(313)

# plot algo performance
pd.plot(ax=ax1, y=['value'], legend=False, fontsize=5, rot=0)

# plot up/down chart
pd['pos'] = pd['pnl']
pd['neg'] = pd['pnl']
pd['pos'][pd['pos'] <= 0] = np.nan
pd['neg'][pd['neg'] > 0] = np.nan
pd.plot(ax=ax2, y=['pos', 'neg'], kind='area', stacked=False, color=['green', 'red'], legend=False, linewidth=0, fontsize=5, rot=0)

# annotate with key data
ax1.set_title('Performance')
ax1.set_ylabel('Portfolio value($)')
for xy in [portfolio_value[0]] + [portfolio_value[-1]]:
for xy in [portfolio_value[0][:2]] + [portfolio_value[-1][:2]]:
ax1.annotate('$%s' % xy[1], xy=xy, textcoords='data')
ax2.annotate('$%s' % xy[1], xy=xy, textcoords='data')
ax3.annotate('$%s' % xy[1], xy=xy, textcoords='data')

ax2.set_title('Trades')
ax2.set_ylabel('Intent/Action')
ax2.set_xlabel('Date')
# plot trade intent/trade action
ax3.set_ylabel('Intent/Action')
ax3.set_xlabel('Date')

ax2.plot([x.time for x in requests if x.side == Side.BUY],
ax3.plot(trades)
ax3.plot([x.time for x in requests if x.side == Side.BUY],
[x.price for x in requests if x.side == Side.BUY],
'2', color='y')
ax2.plot([x.time for x in requests if x.side == Side.SELL],
ax3.plot([x.time for x in requests if x.side == Side.SELL],
[x.price for x in requests if x.side == Side.SELL],
'1', color='y')
ax2.plot([x.time for x in responses if x.side == Side.BUY], # FIXME
ax3.plot([x.time for x in responses if x.side == Side.BUY], # FIXME
[x.price for x in responses if x.side == Side.BUY],
'^', color='g')
ax2.plot([x.time for x in responses if x.side == Side.SELL], # FIXME
ax3.plot([x.time for x in responses if x.side == Side.SELL], # FIXME
[x.price for x in responses if x.side == Side.SELL],
'v', color='r')
ax2.plot(trades)

# set same limits
y_bot, y_top = ax1.get_ylim()
x_bot, x_top = ax1.get_xlim()
ax2.set_ylim(y_bot, y_top)
ax2.set_xlim(x_bot, x_top)

ax3.set_ylim(y_bot, y_top)
ax3.set_xlim(x_bot, x_top)
plt.show()

print(requests)
print(responses)

def onChange(self, data: MarketData) -> None:
pass

Expand Down
8 changes: 5 additions & 3 deletions aat/trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,14 @@ def recalculate_value(self, data: MarketData) -> None:
# nothing to do
return
volume = self._holdings[data.instrument][2]
purchase_price = self._holdings[data.instrument][1] # takes into account slippage/txn cost

if self._portfolio_value == []:
# start from first tick of data
# TODO risk boungs?
# TODO risk bounds?
# self._portfolio_value = [[data.time, self._rk.total_funds]]
self._portfolio_value = [[data.time, volume*data.price]]
self._portfolio_value.append([data.time, volume*data.price])
self._portfolio_value = [[data.time, volume*data.price, volume*(data.price-purchase_price)]]
self._portfolio_value.append([data.time, volume*data.price, volume*(data.price-purchase_price)])

def update_holdings(self, resp: TradeResponse) -> None:
# TODO move to risk
Expand Down
Binary file modified docs/img/bt.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 801a9cb

Please sign in to comment.