mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 00:05:15 +00:00
Merge pull request #633 from zenixls2/fix/ewo_entry
Fix/ewo entry, backtest
This commit is contained in:
commit
8652b4e043
|
@ -155,7 +155,7 @@ const ordersToMarkets = (interval: string, orders: Array<Order> | void): Array<M
|
|||
// var markers = [{ time: data[data.length - 48].time, position: 'aboveBar', color: '#f68410', shape: 'circle', text: 'D' }];
|
||||
for (let i = 0; i < orders.length; i++) {
|
||||
let order = orders[i];
|
||||
let t = order.update_time.getTime() / 1000.0;
|
||||
let t = (order.update_time || order.time).getTime() / 1000.0;
|
||||
let lastMarker = markers.length > 0 ? markers[markers.length - 1] : null;
|
||||
if (lastMarker) {
|
||||
let remainder = lastMarker.time % intervalSecs;
|
||||
|
@ -264,7 +264,7 @@ const positionBaseHistoryToLineData = (interval: string, hs: Array<PositionHisto
|
|||
}
|
||||
|
||||
// ignore duplicated entry
|
||||
if (hs[i].time.getTime() === hs[i - 1].time.getTime()) {
|
||||
if (i > 0 && hs[i].time.getTime() === hs[i - 1].time.getTime()) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,7 @@ const positionAverageCostHistoryToLineData = (interval: string, hs: Array<Positi
|
|||
}
|
||||
|
||||
// ignore duplicated entry
|
||||
if (hs[i].time.getTime() === hs[i - 1].time.getTime()) {
|
||||
if (i > 0 && hs[i].time.getTime() === hs[i - 1].time.getTime()) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -10,20 +10,29 @@ exchangeStrategies:
|
|||
- on: binance
|
||||
ewo_dgtrd:
|
||||
symbol: MATICUSDT
|
||||
interval: 2h
|
||||
# kline interval for indicators
|
||||
interval: 15m
|
||||
# use ema as MA
|
||||
useEma: false
|
||||
# use sma as MA, used when ema is false
|
||||
# if both sma and ema are false, use EVMA
|
||||
useSma: false
|
||||
sigWin: 8
|
||||
stoploss: 10%
|
||||
# ewo signal line window size
|
||||
sigWin: 5
|
||||
# SL percentage from entry price
|
||||
stoploss: 2%
|
||||
# use HeikinAshi klines instead of normal OHLC
|
||||
useHeikinAshi: true
|
||||
# disable SL when short
|
||||
disableShortStop: false
|
||||
#stops:
|
||||
#- trailingStop:
|
||||
# callbackRate: 5.1%
|
||||
# closePosition: 20%
|
||||
# minProfit: 1%
|
||||
# interval: 1m
|
||||
# virtual: true
|
||||
# disable SL when long
|
||||
disableLongStop: false
|
||||
# CCI Stochastic Indicator high filter
|
||||
ccistochFilterHigh: 80
|
||||
# CCI Stochastic Indicator low filter
|
||||
ccistochFilterLow: 20
|
||||
# print record exit point in log messages
|
||||
record: false
|
||||
|
||||
sync:
|
||||
userDataStream:
|
||||
|
@ -36,7 +45,7 @@ sync:
|
|||
|
||||
backtest:
|
||||
startTime: "2022-05-01"
|
||||
endTime: "2022-05-11"
|
||||
endTime: "2022-05-27"
|
||||
symbols:
|
||||
- MATICUSDT
|
||||
sessions: [binance]
|
||||
|
@ -45,5 +54,5 @@ backtest:
|
|||
#makerFeeRate: 0
|
||||
#takerFeeRate: 15
|
||||
balances:
|
||||
MATIC: 5000.0
|
||||
USDT: 10000
|
||||
MATIC: 000.0
|
||||
USDT: 15000.0
|
||||
|
|
|
@ -281,11 +281,11 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
|||
return e.markets, nil
|
||||
}
|
||||
|
||||
func (e Exchange) QueryDepositHistory(ctx context.Context, asset string, since, until time.Time) (allDeposits []types.Deposit, err error) {
|
||||
func (e *Exchange) QueryDepositHistory(ctx context.Context, asset string, since, until time.Time) (allDeposits []types.Deposit, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (e Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []types.Withdraw, err error) {
|
||||
func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []types.Withdraw, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -410,6 +410,15 @@ func (m *SimplePriceMatching) SellToPrice(price fixedpoint.Value) (closedOrders
|
|||
func (m *SimplePriceMatching) processKLine(kline types.KLine) {
|
||||
m.CurrentTime = kline.EndTime.Time()
|
||||
m.LastKLine = kline
|
||||
if m.LastPrice.IsZero() {
|
||||
m.LastPrice = kline.Open
|
||||
} else {
|
||||
if m.LastPrice.Compare(kline.Open) > 0 {
|
||||
m.SellToPrice(kline.Open)
|
||||
} else {
|
||||
m.BuyToPrice(kline.Open)
|
||||
}
|
||||
}
|
||||
|
||||
switch kline.Direction() {
|
||||
case types.DirectionDown:
|
||||
|
|
|
@ -34,7 +34,6 @@ func (s *BacktestService) SyncKLineByInterval(ctx context.Context, exchange type
|
|||
if err := s.BatchInsert(klines); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
count += len(klines)
|
||||
}
|
||||
log.Debugf("inserted klines %s %s data: %d", symbol, interval.String(), count)
|
||||
|
@ -321,8 +320,11 @@ func (s *BacktestService) BatchInsert(kline []types.KLine) error {
|
|||
sql := fmt.Sprintf("INSERT INTO `%s` (`exchange`, `start_time`, `end_time`, `symbol`, `interval`, `open`, `high`, `low`, `close`, `closed`, `volume`, `quote_volume`, `taker_buy_base_volume`, `taker_buy_quote_volume`)"+
|
||||
" values (:exchange, :start_time, :end_time, :symbol, :interval, :open, :high, :low, :close, :closed, :volume, :quote_volume, :taker_buy_base_volume, :taker_buy_quote_volume); ", tableName)
|
||||
|
||||
_, err := s.DB.NamedExec(sql, kline)
|
||||
tx := s.DB.MustBegin()
|
||||
if _, err := tx.NamedExec(sql, kline); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (s *BacktestService) _deleteDuplicatedKLine(k types.KLine) error {
|
||||
|
|
86
pkg/strategy/ewoDgtrd/heikinashi.go
Normal file
86
pkg/strategy/ewoDgtrd/heikinashi.go
Normal file
|
@ -0,0 +1,86 @@
|
|||
package ewoDgtrd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type Queue struct {
|
||||
arr []float64
|
||||
size int
|
||||
}
|
||||
|
||||
func NewQueue(size int) *Queue {
|
||||
return &Queue{
|
||||
arr: make([]float64, 0, size),
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
|
||||
func (inc *Queue) Last() float64 {
|
||||
if len(inc.arr) == 0 {
|
||||
return 0
|
||||
}
|
||||
return inc.arr[len(inc.arr)-1]
|
||||
}
|
||||
|
||||
func (inc *Queue) Index(i int) float64 {
|
||||
if len(inc.arr)-i-1 < 0 {
|
||||
return 0
|
||||
}
|
||||
return inc.arr[len(inc.arr)-i-1]
|
||||
}
|
||||
|
||||
func (inc *Queue) Length() int {
|
||||
return len(inc.arr)
|
||||
}
|
||||
|
||||
func (inc *Queue) Update(v float64) {
|
||||
inc.arr = append(inc.arr, v)
|
||||
if len(inc.arr) > inc.size {
|
||||
inc.arr = inc.arr[len(inc.arr)-inc.size:]
|
||||
}
|
||||
}
|
||||
|
||||
type HeikinAshi struct {
|
||||
Close *Queue
|
||||
Open *Queue
|
||||
High *Queue
|
||||
Low *Queue
|
||||
Volume *Queue
|
||||
}
|
||||
|
||||
func NewHeikinAshi(size int) *HeikinAshi {
|
||||
return &HeikinAshi{
|
||||
Close: NewQueue(size),
|
||||
Open: NewQueue(size),
|
||||
High: NewQueue(size),
|
||||
Low: NewQueue(size),
|
||||
Volume: NewQueue(size),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HeikinAshi) Print() string {
|
||||
return fmt.Sprintf("Heikin c: %.3f, o: %.3f, h: %.3f, l: %.3f, v: %.3f",
|
||||
s.Close.Last(),
|
||||
s.Open.Last(),
|
||||
s.High.Last(),
|
||||
s.Low.Last(),
|
||||
s.Volume.Last())
|
||||
}
|
||||
|
||||
func (inc *HeikinAshi) Update(kline types.KLine) {
|
||||
open := kline.Open.Float64()
|
||||
cloze := kline.Close.Float64()
|
||||
high := kline.High.Float64()
|
||||
low := kline.Low.Float64()
|
||||
newClose := (open + high + low + cloze) / 4.
|
||||
newOpen := (inc.Open.Last() + inc.Close.Last()) / 2.
|
||||
inc.Close.Update(newClose)
|
||||
inc.Open.Update(newOpen)
|
||||
inc.High.Update(math.Max(math.Max(high, newOpen), newClose))
|
||||
inc.Low.Update(math.Min(math.Min(low, newOpen), newClose))
|
||||
inc.Volume.Update(kline.Volume.Float64())
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -9,3 +9,8 @@ func tryLock(lock *sync.RWMutex) bool {
|
|||
lock.Lock()
|
||||
return true
|
||||
}
|
||||
|
||||
func tryRLock(lock *sync.RWMutex) bool {
|
||||
lock.RLock()
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -8,3 +8,7 @@ import "sync"
|
|||
func tryLock(lock *sync.RWMutex) bool {
|
||||
return lock.TryLock()
|
||||
}
|
||||
|
||||
func tryRLock(lock *sync.RWMutex) bool {
|
||||
return lock.TryRLock()
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ func (p *Position) NewProfit(trade Trade, profit, netProfit fixedpoint.Value) Pr
|
|||
|
||||
func (p *Position) NewClosePositionOrder(percentage fixedpoint.Value) *SubmitOrder {
|
||||
base := p.GetBase()
|
||||
quantity := base.Mul(percentage)
|
||||
quantity := base.Mul(percentage).Abs()
|
||||
if quantity.Compare(p.Market.MinQuantity) < 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user