Skip to content
This repository was archived by the owner on Oct 5, 2021. It is now read-only.

Commit ad8262a

Browse files
committed
updating backtester, need to automate _portfolio_value.
1 parent 8b6b06f commit ad8262a

File tree

10 files changed

+187
-151
lines changed

10 files changed

+187
-151
lines changed

algocoin/backtest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ def run(self, engine) -> None:
1616
with open(self._file, 'r') as fp:
1717
for line in fp:
1818
self.receive(line)
19-
engine.tick()
19+
# engine.tick()
2020
log.info('Backtest done, running analysis.')
2121

22+
import ipdb; ipdb.set_trace()
2223
self.callback(TickType.ANALYZE, None)
2324

2425
log.info('Analysis completed.')

algocoin/custom_strategies.py

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import numpy
22
from .lib.strategy import TradingStrategy
33
from .lib.structs import MarketData, TradeRequest, TradeResponse
4-
from .lib.enums import Side
4+
from .lib.enums import Side, OrderType
55
from .lib.logging import STRAT as slog, ERROR as elog
66

77

@@ -23,32 +23,26 @@ def __init__(self, size: int) -> None:
2323
self._portfolio_value = []
2424

2525
def onBuy(self, res: TradeResponse) -> None:
26-
if not res.success:
27-
slog.critical('order failure: %s', res)
28-
return
29-
3026
if self._intitialvalue is None:
31-
date = res.data.time
27+
date = res.time
3228
self._intitialvalue = (date, res.volume*res.price)
3329
self._portfolio_value.append(self._intitialvalue)
3430

3531
self.bought = res.volume*res.price
3632
self.bought_qty = res.volume
37-
slog.critical('d->g:bought %.2f @ %.2f for %.2f', res.volume, res.price, self.bought)
33+
slog.info('d->g:bought %.2f @ %.2f for %.2f', res.volume, res.price, self.bought)
3834

3935
def onSell(self, res: TradeResponse) -> None:
40-
if not res.success:
41-
slog.info('order failure: %s' % res)
42-
return
43-
4436
sold = res.volume*res.price
4537
profit = sold - self.bought
4638
self.profits += profit
47-
slog.critical('g->d:sold %.2f @ %.2f for %.2f - %.2f - %.2f', res.volume, res.price, sold, profit, self.profits)
39+
40+
slog.info('g->d:sold %.2f @ %.2f for %.2f - %.2f - %.2f', res.volume, res.price, sold, profit, self.profits)
41+
4842
self.bought = 0.0
4943
self.bought_qty = 0.0
5044

51-
date = res.data.time
45+
date = res.time
5246
self._portfolio_value.append((
5347
date,
5448
self._portfolio_value[-1][1] + profit))
@@ -68,12 +62,9 @@ def onTrade(self, data: MarketData):
6862
y = numpy.array(self.ticks)
6963
z = numpy.polyfit(self.x, y, 1) # linreg
7064

71-
# print(z)
7265
shouldbuy = z[0] > .2
7366
shouldsell = z[0] < .2
7467

75-
# slog.critical('%.2f %.2f', z[0], data.price)
76-
7768
# sell out if losing too much
7869
# stoploss = (self.bought - data.price*self.bought_qty) > 5
7970
stoploss = False
@@ -90,24 +81,24 @@ def onTrade(self, data: MarketData):
9081

9182
if self.state == 'buy' and self.prev_state != 'buy' and \
9283
self.bought == 0.0: # watch for floating point error
93-
req = TradeRequest(data=data,
94-
side=Side.BUY,
84+
req = TradeRequest(side=Side.BUY,
9585
# buy between .2 and 1 BTC
9686
volume=max(min(1.0, data.volume), .2),
9787
currency=data.currency,
98-
price=data.price)
99-
# slog.critical("requesting buy : %s", req)
88+
price=data.price,
89+
order_type=OrderType.MARKET,
90+
time=data.time)
10091
self.requestBuy(self.onBuy, req)
10192
return True
10293

10394
elif self.state == 'sell' and self.prev_state != 'sell' and \
10495
self.bought > 0.0:
105-
req = TradeRequest(data=data,
106-
side=Side.SELL,
96+
req = TradeRequest(side=Side.SELL,
10797
volume=self.bought_qty,
10898
currency=data.currency,
109-
price=data.price)
110-
# slog.critical("requesting sell : %s", req)
99+
price=data.price,
100+
order_type=OrderType.MARKET,
101+
time=data.time)
111102
self.requestSell(self.onSell, req)
112103
return True
113104

@@ -118,39 +109,39 @@ def onError(self, e: MarketData):
118109

119110
def onAnalyze(self, _):
120111
import pandas
121-
# import matplotlib.pyplot as plt
122-
# import seaborn as sns
112+
import matplotlib.pyplot as plt
113+
import seaborn as sns
123114

124-
## pd = pandas.DataFrame(self._actions,
125-
## columns=['time', 'action', 'price'])
115+
# pd = pandas.DataFrame(self._actions,
116+
# columns=['time', 'action', 'price'])
126117

127118
pd = pandas.DataFrame(self._portfolio_value, columns=['time', 'value'])
128119
pd.set_index(['time'], inplace=True)
129120

130121
print(self.size, pd.iloc[1].value, pd.iloc[-1].value)
131-
## sp500 = pandas.DataFrame()
132-
## tmp = pandas.read_csv('./data/sp/sp500_v_kraken.csv')
133-
## sp500['Date'] = pandas.to_datetime(tmp['Date'])
134-
## sp500['Close'] = tmp['Close']
135-
## sp500.set_index(['Date'], inplace=True)
136-
## print(sp500)
122+
# sp500 = pandas.DataFrame()
123+
# tmp = pandas.read_csv('./data/sp/sp500_v_kraken.csv')
124+
# sp500['Date'] = pandas.to_datetime(tmp['Date'])
125+
# sp500['Close'] = tmp['Close']
126+
# sp500.set_index(['Date'], inplace=True)
127+
# print(sp500)
137128

138-
# sns.set_style('darkgrid')
139-
# fig, ax1 = plt.subplots()
129+
sns.set_style('darkgrid')
130+
fig, ax1 = plt.subplots()
140131

141132
# plt.title('BTC algo 1 performance - %d-%d Momentum ' % (self.short, self.long))
142-
# ax1.plot(pd)
133+
ax1.plot(pd)
143134

144-
# ax1.set_ylabel('Portfolio value($)')
145-
# ax1.set_xlabel('Date')
146-
# for xy in [self._portfolio_value[0]] + [self._portfolio_value[-1]]:
147-
# ax1.annotate('$%s' % xy[1], xy=xy, textcoords='data')
135+
ax1.set_ylabel('Portfolio value($)')
136+
ax1.set_xlabel('Date')
137+
for xy in [self._portfolio_value[0]] + [self._portfolio_value[-1]]:
138+
ax1.annotate('$%s' % xy[1], xy=xy, textcoords='data')
148139

149-
## ax2 = ax1.twinx()
150-
## ax2.plot(sp500, 'r')
151-
## ax2.set_ylabel('S&P500 ($)')
140+
# ax2 = ax1.twinx()
141+
# ax2.plot(sp500, 'r')
142+
# ax2.set_ylabel('S&P500 ($)')
152143

153-
# plt.show()
144+
plt.show()
154145

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

algocoin/lib/parser.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ def _parse_exchange(exchange, config) -> None:
6565

6666
def _parse_strategy(strategy, config) -> None:
6767
strat_configs = []
68-
6968
if 'strategies' not in strategy:
7069
raise Exception('No Strategies specified')
7170

@@ -77,7 +76,7 @@ def _parse_strategy(strategy, config) -> None:
7776

7877
args = []
7978
for x in splits[1:]:
80-
args.append(float(x) if x.isdigit() else x)
79+
args.append(float(x.strip()) if x.strip().isdigit() else x)
8180
args = tuple(args)
8281

8382
strat_configs.append(StrategyConfig(clazz=cls, args=args))

algocoin/lib/strategies/sma_crosses_strategy.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def __init__(self, size_short: int, size_long: int) -> None:
2727

2828
def onBuy(self, res: TradeResponse) -> None:
2929
if not res.status == TradeResult.FILLED:
30-
slog.critical('order failure: %s' % res)
30+
slog.info('order failure: %s' % res)
3131
return
3232

3333
if self._intitialvalue is None:
@@ -37,7 +37,7 @@ def onBuy(self, res: TradeResponse) -> None:
3737

3838
self.bought = res.volume*res.price
3939
self.bought_qty = res.volume
40-
slog.critical('d->g:bought %.2f @ %.2f for %.2f ---- %.2f %.2f' % (res.volume, res.price, self.bought, self.short_av, self.long_av))
40+
slog.info('d->g:bought %.2f @ %.2f for %.2f ---- %.2f %.2f' % (res.volume, res.price, self.bought, self.short_av, self.long_av))
4141

4242
def onSell(self, res: TradeResponse) -> None:
4343
if not res.status == TradeResult.FILLED:
@@ -47,7 +47,7 @@ def onSell(self, res: TradeResponse) -> None:
4747
sold = res.volume*res.price
4848
profit = sold - self.bought
4949
self.profits += profit
50-
slog.critical('g->d:sold %.2f @ %.2f for %.2f - %.2f - %.2f ---- %.2f %.2f' % (res.volume, res.price, sold, profit, self.profits, self.short_av, self.long_av))
50+
slog.info('g->d:sold %.2f @ %.2f for %.2f - %.2f - %.2f ---- %.2f %.2f' % (res.volume, res.price, sold, profit, self.profits, self.short_av, self.long_av))
5151
self.bought = 0.0
5252
self.bought_qty = 0.0
5353

@@ -72,7 +72,7 @@ def onTrade(self, data: MarketData) -> bool:
7272
self.short_av = float(sum(self.shorts)) / max(len(self.shorts), 1)
7373
self.long_av = float(sum(self.longs)) / max(len(self.longs), 1)
7474

75-
slog.critical('%.2f %.2f', self.short_av, self.long_av)
75+
slog.info('%.2f %.2f', self.short_av, self.long_av)
7676
# sell out if losing too much
7777
stoploss = (self.bought - data.price*self.bought_qty) > 5
7878
# stoploss = False
@@ -98,7 +98,7 @@ def onTrade(self, data: MarketData) -> bool:
9898
currency=data.currency,
9999
order_type=OrderType.MARKET,
100100
price=data.price)
101-
# slog.critical("requesting buy : %s", req)
101+
# slog.info("requesting buy : %s", req)
102102
self.requestBuy(self.onBuy, req)
103103
return True
104104

@@ -109,7 +109,7 @@ def onTrade(self, data: MarketData) -> bool:
109109
currency=data.currency,
110110
order_type=OrderType.MARKET,
111111
price=data.price)
112-
# slog.critical("requesting sell : %s", req)
112+
# slog.info("requesting sell : %s", req)
113113
self.requestSell(self.onSell, req)
114114
return True
115115

@@ -120,39 +120,39 @@ def onError(self, e) -> None:
120120

121121
def onAnalyze(self, _) -> None:
122122
import pandas
123-
# import matplotlib.pyplot as plt
124-
# import seaborn as sns
123+
import matplotlib.pyplot as plt
124+
import seaborn as sns
125125

126-
## pd = pandas.DataFrame(self._actions,
127-
## columns=['time', 'action', 'price'])
126+
# pd = pandas.DataFrame(self._actions,
127+
# columns=['time', 'action', 'price'])
128128

129129
pd = pandas.DataFrame(self._portfolio_value, columns=['time', 'value'])
130130
pd.set_index(['time'], inplace=True)
131131

132132
print(self.short, self.long, pd.iloc[1].value, pd.iloc[-1].value)
133-
## sp500 = pandas.DataFrame()
134-
## tmp = pandas.read_csv('./data/sp/sp500_v_kraken.csv')
135-
## sp500['Date'] = pandas.to_datetime(tmp['Date'])
136-
## sp500['Close'] = tmp['Close']
137-
## sp500.set_index(['Date'], inplace=True)
138-
## print(sp500)
133+
# sp500 = pandas.DataFrame()
134+
# tmp = pandas.read_csv('./data/sp/sp500_v_kraken.csv')
135+
# sp500['Date'] = pandas.to_datetime(tmp['Date'])
136+
# sp500['Close'] = tmp['Close']
137+
# sp500.set_index(['Date'], inplace=True)
138+
# print(sp500)
139139

140-
# sns.set_style('darkgrid')
141-
# fig, ax1 = plt.subplots()
140+
sns.set_style('darkgrid')
141+
fig, ax1 = plt.subplots()
142142

143-
# plt.title('BTC algo 1 performance - %d-%d Momentum ' % (self.short, self.long))
144-
# ax1.plot(pd)
143+
plt.title('BTC algo 1 performance - %d-%d Momentum ' % (self.short, self.long))
144+
ax1.plot(pd)
145145

146-
# ax1.set_ylabel('Portfolio value($)')
147-
# ax1.set_xlabel('Date')
148-
# for xy in [self._portfolio_value[0]] + [self._portfolio_value[-1]]:
149-
# ax1.annotate('$%s' % xy[1], xy=xy, textcoords='data')
146+
ax1.set_ylabel('Portfolio value($)')
147+
ax1.set_xlabel('Date')
148+
for xy in [self._portfolio_value[0]] + [self._portfolio_value[-1]]:
149+
ax1.annotate('$%s' % xy[1], xy=xy, textcoords='data')
150150

151-
## ax2 = ax1.twinx()
152-
## ax2.plot(sp500, 'r')
153-
## ax2.set_ylabel('S&P500 ($)')
151+
# ax2 = ax1.twinx()
152+
# ax2.plot(sp500, 'r')
153+
# ax2.set_ylabel('S&P500 ($)')
154154

155-
# plt.show()
155+
plt.show()
156156

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

algocoin/lib/strategies/sma_crosses_strategy_with_regression_follow.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def __init__(self, size_short: int, size_long: int) -> None:
3535

3636
def onBuy(self, res: TradeResponse) -> None:
3737
if not res.success:
38-
slog.critical('order failure: %s' % res)
38+
slog.info('order failure: %s' % res)
3939
return
4040

4141
if self._intitialvalue is None:
@@ -45,7 +45,7 @@ def onBuy(self, res: TradeResponse) -> None:
4545

4646
self.bought = res.volume*res.price
4747
self.bought_qty = res.volume
48-
slog.critical('d->g:bought %.2f @ %.2f for %.2f ---- %.2f %.2f' % (res.volume, res.price, self.bought, self.short_av, self.long_av))
48+
slog.info('d->g:bought %.2f @ %.2f for %.2f ---- %.2f %.2f' % (res.volume, res.price, self.bought, self.short_av, self.long_av))
4949

5050
def onSell(self, res: TradeResponse) -> None:
5151
if not res.success:
@@ -55,7 +55,7 @@ def onSell(self, res: TradeResponse) -> None:
5555
sold = res.volume*res.price
5656
profit = sold - self.bought
5757
self.profits += profit
58-
slog.critical('g->d:sold %.2f @ %.2f for %.2f - %.2f - %.2f ---- %.2f %.2f' % (res.volume, res.price, sold, profit, self.profits, self.short_av, self.long_av))
58+
slog.info('g->d:sold %.2f @ %.2f for %.2f - %.2f - %.2f ---- %.2f %.2f' % (res.volume, res.price, sold, profit, self.profits, self.short_av, self.long_av))
5959
self.bought = 0.0
6060
self.bought_qty = 0.0
6161

@@ -88,7 +88,7 @@ def onTrade(self, data: MarketData) -> bool:
8888
short_trend = short_h[0]
8989
long_trend = long_h[0]
9090

91-
slog.critical('ave : %.2f %.2f \ttrend :', self.short_av, self.long_av, short_trend, long_trend)
91+
slog.info('ave : %.2f %.2f \ttrend :', self.short_av, self.long_av, short_trend, long_trend)
9292
# sell out if losing too much
9393
stoploss = (self.bought - data.price*self.bought_qty) > 5
9494
# stoploss = False
@@ -114,7 +114,7 @@ def onTrade(self, data: MarketData) -> bool:
114114
volume=max(min(1.0, data.volume), .2),
115115
currency=data.currency,
116116
price=data.price)
117-
# slog.critical("requesting buy : %s", req)
117+
# slog.info("requesting buy : %s", req)
118118
self.requestBuy(self.onBuy, req)
119119
return True
120120

@@ -125,7 +125,7 @@ def onTrade(self, data: MarketData) -> bool:
125125
volume=self.bought_qty,
126126
currency=data.currency,
127127
price=data.price)
128-
# slog.critical("requesting sell : %s", req)
128+
# slog.info("requesting sell : %s", req)
129129
self.requestSell(self.onSell, req)
130130
return True
131131

0 commit comments

Comments
 (0)