Skip to content

Commit 601de72

Browse files
committed
provide a simple public version of a dip / retracement strategy
1 parent ed06bce commit 601de72

File tree

5 files changed

+196
-7
lines changed

5 files changed

+196
-7
lines changed

README.md

+17-7
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,15 @@ Currently there is a the UI for backtesting
194194

195195
![Webserver UI](documentation/manual_order.png "Manual Orders")
196196

197-
## Fill data
197+
## Build In Strategies
198198

199-
```
200-
node index.js backfill -e bitmex -p 1m -s XRPZ18
201-
```
199+
Common strategy with indicators are inside, which most of the time are not profitable. See some more advanced strategy in the list below
200+
201+
* [dip_catcher](src/modules/strategy/strategies/dip_catcher/README.md)
202202

203-
## Strategies
203+
Find some example strategies inside [src/modules/strategy/strategies](src/modules/strategy/strategies)
204+
205+
## Custom Strategies
204206

205207
For custom strategies use [var/strategies](var/strategies) folder.
206208

@@ -213,8 +215,6 @@ var/strategies/my_strategy/my_strategy.js
213215
var/strategies/subfolder1/our_strategy/our_strategy.js
214216
```
215217

216-
Find some example strategies inside [modules/strategy/strategies](modules/strategy/strategies)
217-
218218
## Tools / Watchdog
219219

220220
* `order_adjust` Keep open orders in bid / ask of the orderbook in first position
@@ -378,6 +378,16 @@ Per pair you can set used margin before orders are created; depending on exchang
378378
})
379379
```
380380

381+
## Tools
382+
383+
### Fill data
384+
385+
*outdated*, but there as an automatic filling on startup ~1000 candles from the past (depending on exchange) and continuously fetched when running
386+
387+
```
388+
node index.js backfill -e bitmex -p 1m -s XRPZ18
389+
```
390+
381391
## Signals
382392

383393
### Slack
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Dip / Retracement Catcher
2+
3+
Try to catch a dip or retracement on the higher trend
4+
5+
## Trend Indicator
6+
7+
Ichimoku Cloud "Lead2 Line" given the "long" or "short" trend based on higher timeframe (4x multipler of main period)
8+
9+
## Entry / Exit
10+
11+
HMA (source: candle low) is cross from lower Bollinger for vice versa for opposite signal
12+
13+
## Configuration
14+
15+
Default config is more secure given less signals.
16+
17+
```json
18+
{
19+
"period": "15m",
20+
"trend_cloud_multiplier": 4,
21+
"hma_high_period": 9,
22+
"hma_high_candle_source": "close",
23+
"hma_low_period": 9,
24+
"hma_low_candle_source": "close"
25+
}
26+
```
27+
28+
More signals can be generate by change the candle source and higher the signal line
29+
30+
```json
31+
{
32+
"period": "15m",
33+
"trend_cloud_multiplier": 4,
34+
"hma_high_period": 12,
35+
"hma_high_candle_source": "high",
36+
"hma_low_period": 12,
37+
"hma_low_candle_source": "low"
38+
}
39+
```
40+
41+
## Tradingview
42+
43+
![Tradingview](doc/dip_catcher_tradingview.png)
44+
45+
## Backtest
46+
47+
![Backtest](doc/dip_catcher_backtest.png)
48+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
const SignalResult = require('../../dict/signal_result');
2+
3+
module.exports = class DipCatcher {
4+
getName() {
5+
return 'dip_catcher';
6+
}
7+
8+
buildIndicator(indicatorBuilder, options) {
9+
// line for short entry or long exit
10+
indicatorBuilder.add('hma_high', 'hma', options.period, {
11+
length: options.hma_high_period || 12,
12+
source: options.hma_high_candle_source || 'high'
13+
});
14+
15+
// line for long entry or short exit
16+
indicatorBuilder.add('hma_low', 'hma', options.period, {
17+
length: options.hma_low_period || 12,
18+
source: options.hma_low_candle_source || 'low'
19+
});
20+
21+
// basic price normalizer
22+
indicatorBuilder.add('hma', 'hma', options.period, {
23+
length: 9
24+
});
25+
26+
// our main direction
27+
const trendCloudMultiplier = options.trend_cloud_multiplier || 4;
28+
indicatorBuilder.add('cloud', 'ichimoku_cloud', options.period, {
29+
conversionPeriod: 9 * trendCloudMultiplier,
30+
basePeriod: 26 * trendCloudMultiplier,
31+
spanPeriod: 52 * trendCloudMultiplier,
32+
displacement: 26 * trendCloudMultiplier
33+
});
34+
35+
indicatorBuilder.add('bb', 'bb', '15m');
36+
}
37+
38+
period(indicatorPeriod) {
39+
const currentValues = indicatorPeriod.getLatestIndicators();
40+
41+
const hma = indicatorPeriod.getIndicator('hma').slice(-2);
42+
const hmaLow = indicatorPeriod.getIndicator('hma_low').slice(-2);
43+
const hmaHigh = indicatorPeriod.getIndicator('hma_high').slice(-2);
44+
const bb = indicatorPeriod.getIndicator('bb').slice(-2);
45+
const cloud = indicatorPeriod.getIndicator('cloud').slice(-1);
46+
47+
const emptySignal = SignalResult.createEmptySignal(currentValues);
48+
49+
if (!cloud[0] || !hma[0]) {
50+
return emptySignal;
51+
}
52+
53+
const lastSignal = indicatorPeriod.getLastSignal();
54+
55+
// follow the main trend with entries
56+
const isLong = hma[0] > cloud[0].spanB;
57+
emptySignal.addDebug('trend', isLong);
58+
59+
if (hmaLow[0] > bb[0].lower && hmaLow[1] < bb[1].lower) {
60+
if (!lastSignal && isLong) {
61+
emptySignal.addDebug('message', 'long_lower_cross');
62+
63+
emptySignal.setSignal('long');
64+
} else if (lastSignal) {
65+
emptySignal.setSignal('close');
66+
}
67+
}
68+
69+
if (hmaHigh[0] < bb[0].upper && hmaHigh[1] > bb[1].upper) {
70+
if (!lastSignal && !isLong) {
71+
emptySignal.addDebug('message', 'short_upper_cross');
72+
73+
emptySignal.setSignal('short');
74+
} else if (lastSignal) {
75+
emptySignal.setSignal('close');
76+
}
77+
}
78+
79+
return emptySignal;
80+
}
81+
82+
getBacktestColumns() {
83+
return [
84+
{
85+
label: 'bb_hma',
86+
value: row => {
87+
if (!row.bb) {
88+
return undefined;
89+
}
90+
91+
if (row.hma < row.bb.lower) {
92+
return 'success';
93+
}
94+
95+
if (row.hma > row.bb.upper) {
96+
return 'danger';
97+
}
98+
99+
return undefined;
100+
},
101+
type: 'icon'
102+
},
103+
{
104+
label: 'trend',
105+
value: row => {
106+
if (typeof row.trend !== 'boolean') {
107+
return undefined;
108+
}
109+
110+
return row.trend === true ? 'success' : 'danger';
111+
},
112+
type: 'icon'
113+
},
114+
{
115+
label: 'message',
116+
value: 'message'
117+
}
118+
];
119+
}
120+
121+
getOptions() {
122+
return {
123+
period: '15m',
124+
trend_cloud_multiplier: 4,
125+
hma_high_period: 9,
126+
hma_high_candle_source: 'close',
127+
hma_low_period: 9,
128+
hma_low_candle_source: 'close'
129+
};
130+
}
131+
};
Loading
Loading

0 commit comments

Comments
 (0)