Skip to content

Commit 292dfed

Browse files
committed
strategy: add harmonic shark pattern recognition
1 parent 0d69fb3 commit 292dfed

File tree

5 files changed

+694
-0
lines changed

5 files changed

+694
-0
lines changed

config/harmonic.yaml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
persistence:
2+
json:
3+
directory: var/data
4+
redis:
5+
host: 127.0.0.1
6+
port: 6379
7+
db: 0
8+
9+
sessions:
10+
binance:
11+
exchange: binance
12+
envVarPrefix: binance
13+
14+
exchangeStrategies:
15+
- on: binance
16+
harmonic:
17+
symbol: BTCBUSD
18+
interval: 1s
19+
window: 500
20+
quantity: 0.05
21+
22+
backtest:
23+
sessions:
24+
- binance
25+
startTime: "2022-09-30"
26+
endTime: "2022-10-01"
27+
symbols:
28+
- BTCBUSD
29+
accounts:
30+
binance:
31+
balances:
32+
BTC: 1.0
33+
BUSD: 40_000.0

pkg/cmd/strategy/builtin.go

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
_ "github.com/c9s/bbgo/pkg/strategy/fmaker"
1818
_ "github.com/c9s/bbgo/pkg/strategy/funding"
1919
_ "github.com/c9s/bbgo/pkg/strategy/grid"
20+
_ "github.com/c9s/bbgo/pkg/strategy/harmonic"
2021
_ "github.com/c9s/bbgo/pkg/strategy/irr"
2122
_ "github.com/c9s/bbgo/pkg/strategy/kline"
2223
_ "github.com/c9s/bbgo/pkg/strategy/marketcap"

pkg/strategy/harmonic/shark.go

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package harmonic
2+
3+
import (
4+
"math"
5+
"time"
6+
7+
"github.com/c9s/bbgo/pkg/datatype/floats"
8+
"github.com/c9s/bbgo/pkg/indicator"
9+
"github.com/c9s/bbgo/pkg/types"
10+
)
11+
12+
var zeroTime time.Time
13+
14+
//go:generate callbackgen -type SHARK
15+
type SHARK struct {
16+
types.IntervalWindow
17+
types.SeriesBase
18+
19+
Lows floats.Slice
20+
Highs floats.Slice
21+
LongScores floats.Slice
22+
ShortScores floats.Slice
23+
24+
Values floats.Slice
25+
26+
EndTime time.Time
27+
28+
updateCallbacks []func(value float64)
29+
}
30+
31+
var _ types.SeriesExtend = &SHARK{}
32+
33+
func (inc *SHARK) Update(high, low, price float64) {
34+
if inc.SeriesBase.Series == nil {
35+
inc.SeriesBase.Series = inc
36+
}
37+
inc.Highs.Update(high)
38+
inc.Lows.Update(low)
39+
40+
if inc.Highs.Length() < inc.Window || inc.Lows.Length() < inc.Window {
41+
return
42+
}
43+
44+
longScore := inc.SharkLong(inc.Highs, inc.Lows, price, inc.Window)
45+
shortScore := inc.SharkShort(inc.Highs, inc.Lows, price, inc.Window)
46+
47+
inc.LongScores.Push(longScore)
48+
inc.ShortScores.Push(shortScore)
49+
50+
inc.Values.Push(longScore - shortScore)
51+
52+
}
53+
54+
func (inc *SHARK) Last() float64 {
55+
if len(inc.Values) == 0 {
56+
return 0
57+
}
58+
59+
return inc.Values[len(inc.Values)-1]
60+
}
61+
62+
func (inc *SHARK) Index(i int) float64 {
63+
if i >= len(inc.Values) {
64+
return 0
65+
}
66+
67+
return inc.Values[len(inc.Values)-1-i]
68+
}
69+
70+
func (inc *SHARK) Length() int {
71+
return len(inc.Values)
72+
}
73+
74+
func (inc *SHARK) BindK(target indicator.KLineClosedEmitter, symbol string, interval types.Interval) {
75+
target.OnKLineClosed(types.KLineWith(symbol, interval, inc.PushK))
76+
}
77+
78+
func (inc *SHARK) PushK(k types.KLine) {
79+
if inc.EndTime != zeroTime && k.EndTime.Before(inc.EndTime) {
80+
return
81+
}
82+
83+
inc.Update(indicator.KLineHighPriceMapper(k), indicator.KLineLowPriceMapper(k), indicator.KLineClosePriceMapper(k))
84+
inc.EndTime = k.EndTime.Time()
85+
inc.EmitUpdate(inc.Last())
86+
}
87+
88+
func (inc *SHARK) LoadK(allKLines []types.KLine) {
89+
for _, k := range allKLines {
90+
inc.PushK(k)
91+
}
92+
inc.EmitUpdate(inc.Last())
93+
}
94+
95+
func (inc SHARK) SharkLong(highs, lows floats.Slice, p float64, lookback int) float64 {
96+
score := 0.
97+
for x := 5; x < lookback; x++ {
98+
if lows.Index(x-1) > lows.Index(x) && lows.Index(x) < lows.Index(x+1) {
99+
X := lows.Index(x)
100+
for a := 4; a < x; a++ {
101+
if highs.Index(a-1) < highs.Index(a) && highs.Index(a) > highs.Index(a+1) {
102+
A := highs.Index(a)
103+
XA := math.Abs(X - A)
104+
hB := A - 0.382*XA
105+
lB := A - 0.618*XA
106+
for b := 3; b < a; b++ {
107+
if lows.Index(b-1) > lows.Index(b) && lows.Index(b) < lows.Index(b+1) {
108+
B := lows.Index(b)
109+
if hB > B && B > lB {
110+
//log.Infof("got point B:%f", B)
111+
AB := math.Abs(A - B)
112+
hC := B + 1.618*AB
113+
lC := B + 1.13*AB
114+
for c := 2; c < b; c++ {
115+
if highs.Index(c-1) < highs.Index(c) && highs.Index(c) > highs.Index(c+1) {
116+
C := highs.Index(c)
117+
if hC > C && C > lC {
118+
//log.Infof("got point C:%f", C)
119+
XC := math.Abs(X - C)
120+
hD := C - 0.886*XC
121+
lD := C - 1.13*XC
122+
//for d := 1; d < c; d++ {
123+
//if lows.Index(d-1) > lows.Index(d) && lows.Index(d) < lows.Index(d+1) {
124+
D := p //lows.Index(d)
125+
if hD > D && D > lD {
126+
BC := math.Abs(B - C)
127+
hD2 := C - 1.618*BC
128+
lD2 := C - 2.24*BC
129+
if hD2 > D && D > lD2 {
130+
//log.Infof("got point D:%f", D)
131+
score++
132+
}
133+
}
134+
//}
135+
//}
136+
}
137+
}
138+
}
139+
}
140+
}
141+
}
142+
}
143+
}
144+
}
145+
}
146+
return score
147+
}
148+
149+
func (inc SHARK) SharkShort(highs, lows floats.Slice, p float64, lookback int) float64 {
150+
score := 0.
151+
for x := 5; x < lookback; x++ {
152+
if highs.Index(x-1) < highs.Index(x) && highs.Index(x) > highs.Index(x+1) {
153+
X := highs.Index(x)
154+
for a := 4; a < x; a++ {
155+
if lows.Index(a-1) > lows.Index(a) && lows.Index(a) < lows.Index(a+1) {
156+
A := lows.Index(a)
157+
XA := math.Abs(X - A)
158+
lB := A + 0.382*XA
159+
hB := A + 0.618*XA
160+
for b := 3; b < a; b++ {
161+
if highs.Index(b-1) > highs.Index(b) && highs.Index(b) < highs.Index(b+1) {
162+
B := highs.Index(b)
163+
if hB > B && B > lB {
164+
//log.Infof("got point B:%f", B)
165+
AB := math.Abs(A - B)
166+
lC := B - 1.618*AB
167+
hC := B - 1.13*AB
168+
for c := 2; c < b; c++ {
169+
if lows.Index(c-1) < lows.Index(c) && lows.Index(c) > lows.Index(c+1) {
170+
C := lows.Index(c)
171+
if hC > C && C > lC {
172+
//log.Infof("got point C:%f", C)
173+
XC := math.Abs(X - C)
174+
lD := C + 0.886*XC
175+
hD := C + 1.13*XC
176+
//for d := 1; d < c; d++ {
177+
//if lows.Index(d-1) > lows.Index(d) && lows.Index(d) < lows.Index(d+1) {
178+
D := p //lows.Index(d)
179+
if hD > D && D > lD {
180+
BC := math.Abs(B - C)
181+
lD2 := C + 1.618*BC
182+
hD2 := C + 2.24*BC
183+
if hD2 > D && D > lD2 {
184+
//log.Infof("got point D:%f", D)
185+
score++
186+
}
187+
}
188+
//}
189+
//}
190+
}
191+
}
192+
}
193+
}
194+
}
195+
}
196+
}
197+
}
198+
}
199+
}
200+
return score
201+
}

pkg/strategy/harmonic/shark_callbacks.go

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)