Skip to content

Commit e3a1d47

Browse files
fix(backtesting): fix profits and trade results (#243)
1 parent ec6792c commit e3a1d47

File tree

4 files changed

+43
-55
lines changed

4 files changed

+43
-55
lines changed

examples/strategies/emacross.go

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,45 +54,22 @@ func (e *CrossEMA) OnCandle(df *ninjabot.Dataframe, broker service.Broker) {
5454
return
5555
}
5656

57-
if (quotePosition > 10 || assetPosition*closePrice < -10) && df.Metadata["ema8"].Crossover(df.Metadata["sma21"]) {
58-
if assetPosition < 0 {
59-
// close previous short position
60-
_, err := broker.CreateOrderMarket(ninjabot.SideTypeBuy, df.Pair, -assetPosition)
61-
if err != nil {
62-
log.Error(err)
63-
}
57+
if quotePosition >= 10 && // minimum quote position to trade
58+
df.Metadata["ema8"].Crossover(df.Metadata["sma21"]) { // trade signal (EMA8 > SMA21)
6459

65-
assetPosition, quotePosition, err = broker.Position(df.Pair)
66-
if err != nil {
67-
log.Error(err)
68-
return
69-
}
70-
}
71-
72-
_, err = broker.CreateOrderMarket(ninjabot.SideTypeBuy, df.Pair, quotePosition/closePrice*0.99)
60+
amount := quotePosition / closePrice // calculate amount of asset to buy
61+
_, err := broker.CreateOrderMarket(ninjabot.SideTypeBuy, df.Pair, amount)
7362
if err != nil {
7463
log.Error(err)
7564
}
65+
7666
return
7767
}
7868

79-
if (assetPosition*closePrice > 10 || quotePosition > 10) &&
80-
df.Metadata["ema8"].Crossunder(df.Metadata["sma21"]) {
81-
if assetPosition > 0 {
82-
// close previous long position
83-
_, err := broker.CreateOrderMarket(ninjabot.SideTypeSell, df.Pair, assetPosition)
84-
if err != nil {
85-
log.Error(err)
86-
}
87-
88-
assetPosition, quotePosition, err = broker.Position(df.Pair)
89-
if err != nil {
90-
log.Error(err)
91-
return
92-
}
93-
}
69+
if assetPosition > 0 &&
70+
df.Metadata["ema8"].Crossunder(df.Metadata["sma21"]) { // trade signal (EMA8 < SMA21)
9471

95-
_, err = broker.CreateOrderMarket(ninjabot.SideTypeSell, df.Pair, quotePosition/closePrice*0.99)
72+
_, err = broker.CreateOrderMarket(ninjabot.SideTypeSell, df.Pair, assetPosition)
9673
if err != nil {
9774
log.Error(err)
9875
}

exchange/paperwallet.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ func (p *PaperWallet) CreateOrderOCO(side model.SideType, pair string,
505505
p.Lock()
506506
defer p.Unlock()
507507

508+
if size == 0 {
509+
return nil, ErrInvalidQuantity
510+
}
511+
508512
err := p.validateFunds(side, pair, size, price, false)
509513
if err != nil {
510514
return nil, err
@@ -550,6 +554,10 @@ func (p *PaperWallet) CreateOrderLimit(side model.SideType, pair string,
550554
p.Lock()
551555
defer p.Unlock()
552556

557+
if size == 0 {
558+
return model.Order{}, ErrInvalidQuantity
559+
}
560+
553561
err := p.validateFunds(side, pair, size, limit, false)
554562
if err != nil {
555563
return model.Order{}, err
@@ -580,6 +588,10 @@ func (p *PaperWallet) CreateOrderStop(pair string, size float64, limit float64)
580588
p.Lock()
581589
defer p.Unlock()
582590

591+
if size == 0 {
592+
return model.Order{}, ErrInvalidQuantity
593+
}
594+
583595
err := p.validateFunds(model.SideTypeSell, pair, size, limit, false)
584596
if err != nil {
585597
return model.Order{}, err
@@ -602,6 +614,10 @@ func (p *PaperWallet) CreateOrderStop(pair string, size float64, limit float64)
602614
}
603615

604616
func (p *PaperWallet) createOrderMarket(side model.SideType, pair string, size float64) (model.Order, error) {
617+
if size == 0 {
618+
return model.Order{}, ErrInvalidQuantity
619+
}
620+
605621
err := p.validateFunds(side, pair, size, p.lastCandle[pair].Close, true)
606622
if err != nil {
607623
return model.Order{}, err

order/controller.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,19 +246,16 @@ func (c *Controller) processTrade(order *model.Order) {
246246
// register order volume
247247
c.Results[order.Pair].Volume += order.Price * order.Quantity
248248

249-
// calculate profit only to sell orders
250-
if order.Side != model.SideTypeSell {
251-
return
252-
}
253-
254249
profitValue, profit, err := c.calculateProfit(order)
255250
if err != nil {
256251
c.notifyError(err)
257252
return
258253
}
259254

260255
order.Profit = profit
261-
if profitValue >= 0 {
256+
if profitValue == 0 {
257+
return
258+
} else if profitValue > 0 {
262259
if order.Side == model.SideTypeBuy {
263260
c.Results[order.Pair].WinLong = append(c.Results[order.Pair].WinLong, profitValue)
264261
} else {

readme.md

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![Discord](https://img.shields.io/discord/960156400376483840?color=5865F2&label=discord)](https://discord.gg/TGCrUH972E)
77
[![Discord](https://img.shields.io/badge/donate-patreon-red)](https://www.patreon.com/ninjabot_github)
88

9-
A fast cryptocurrency trading bot framework implemented in Go. Ninjabot permits users to create and test custom strategies for spot markets.
9+
A fast cryptocurrency trading bot framework implemented in Go. Ninjabot permits users to create and test custom strategies for sport and future markets.
1010

1111
Docs: https://rodrigo-brito.github.io/ninjabot/
1212

@@ -49,36 +49,35 @@ go run examples/backtesting/main.go
4949
Output:
5050

5151
```
52-
INFO[2022-10-16 16:34] [SETUP] Using paper wallet
53-
INFO[2022-10-16 16:34] [SETUP] Initial Portfolio = 10000.000000 USDT
54-
+---------+--------+-----+------+--------+--------+-----+----------+-----------+
52+
INFO[2023-03-25 13:54] [SETUP] Using paper wallet
53+
INFO[2023-03-25 13:54] [SETUP] Initial Portfolio = 10000.000000 USDT
54+
---------+--------+-----+------+--------+--------+-----+----------+-----------+
5555
| PAIR | TRADES | WIN | LOSS | % WIN | PAYOFF | SQN | PROFIT | VOLUME |
5656
+---------+--------+-----+------+--------+--------+-----+----------+-----------+
57-
| BTCUSDT | 14 | 6 | 8 | 42.9 % | 5.929 | 1.5 | 13511.66 | 448030.04 |
5857
| ETHUSDT | 9 | 6 | 3 | 66.7 % | 3.407 | 1.3 | 21748.41 | 407769.64 |
58+
| BTCUSDT | 14 | 6 | 8 | 42.9 % | 5.929 | 1.5 | 13511.66 | 448030.05 |
5959
+---------+--------+-----+------+--------+--------+-----+----------+-----------+
6060
| TOTAL | 23 | 12 | 11 | 52.2 % | 4.942 | 1.4 | 35260.07 | 855799.68 |
6161
+---------+--------+-----+------+--------+--------+-----+----------+-----------+
6262
6363
-- FINAL WALLET --
6464
0.0000 BTC = 0.0000 USDT
6565
0.0000 ETH = 0.0000 USDT
66-
45260.0734 USDT
66+
45260.0735 USDT
6767
6868
----- RETURNS -----
6969
START PORTFOLIO = 10000.00 USDT
7070
FINAL PORTFOLIO = 45260.07 USDT
71-
GROSS PROFIT = 35260.073380 USDT (352.60%)
71+
GROSS PROFIT = 35260.073493 USDT (352.60%)
7272
MARKET CHANGE (B&H) = 407.09%
7373
7474
------ RISK -------
7575
MAX DRAWDOWN = -11.76 %
7676
7777
------ VOLUME -----
78+
BTCUSDT = 448030.05 USDT
7879
ETHUSDT = 407769.64 USDT
79-
BTCUSDT = 448030.04 USDT
8080
TOTAL = 855799.68 USDT
81-
COSTS (0.001*V) = 855.80 USDT (ESTIMATION)
8281
-------------------
8382
Chart available at http://localhost:8080
8483
@@ -90,14 +89,14 @@ Chart available at http://localhost:8080
9089

9190
### Features
9291

93-
| | Binance Spot | Binance Futures |
94-
|-------------------- |-------------- |---------------- |
95-
| Order Market | :ok: | :ok: |
96-
| Order Market Quote | :ok: | |
97-
| Order Limit | :ok: | :ok: |
98-
| Order Stop | :ok: | :ok: |
99-
| Order OCO | :ok: | |
100-
| Backtesting | :ok: | :construction: |
92+
| | Binance Spot | Binance Futures |
93+
|-------------------- |-------------- |-------------------|
94+
| Order Market | :ok: | :ok: |
95+
| Order Market Quote | :ok: | |
96+
| Order Limit | :ok: | :ok: |
97+
| Order Stop | :ok: | :ok: |
98+
| Order OCO | :ok: | |
99+
| Backtesting | :ok: | :ok: |
101100

102101
- [x] Backtesting
103102
- [x] Paper Wallet (Live Trading with fake wallet)
@@ -115,7 +114,6 @@ Chart available at http://localhost:8080
115114
# Roadmap
116115
- [ ] Include Web UI Controller
117116
- [ ] Include more chart indicators - [Details](https://github.com/rodrigo-brito/ninjabot/issues/110)
118-
- [ ] Support future market - [Details](https://github.com/rodrigo-brito/ninjabot/issues/106)
119117

120118
### Exchanges
121119

0 commit comments

Comments
 (0)