-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathcdlclosingmarubozu.go
73 lines (64 loc) · 2.71 KB
/
cdlclosingmarubozu.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package talibcdl
import (
"log"
)
// ClosingMarubozu implements ta-lib function TA_CDLCLOSINGMARUBOZU.
//
// | Continuation: 52%
// ░ ▓ Reversal: 48%
// ░ ▓ Common Rank: B-
// ░ ▓ Efficiency Rank: E+
// | Source: feedroll.com
func ClosingMarubozu(series Series) []int {
es := enhancedSeries{series}
outInteger := make([]int, es.Len())
// Identify the minimum number of price bar needed to calculate at least one output.
// Move up the start index if there is not enough initial data.
startIdx := intMax(settingBodyLong.avgPeriod, settingShadowVeryShort.avgPeriod)
// Make sure there is still something to evaluate.
if startIdx >= es.Len() {
log.Printf("too few input len(%d) want(%d)", es.Len(), startIdx)
return outInteger
}
// Do the calculation using tight loops.
// Add-up the initial period, except for the last value.
bodyLongPeriodTotal := 0.0
bodyLongTrailingIdx := startIdx - settingBodyLong.avgPeriod
shadowVeryShortPeriodTotal := 0.0
shadowVeryShortTrailingIdx := startIdx - settingShadowVeryShort.avgPeriod
for i := bodyLongTrailingIdx; i < startIdx; i++ {
bodyLongPeriodTotal += es.rangeOf(settingBodyLong, i)
i++
}
for i := shadowVeryShortTrailingIdx; i < startIdx; i++ {
shadowVeryShortPeriodTotal += es.rangeOf(settingShadowVeryShort, i)
i++
}
/* Proceed with the calculation for the requested range.
* Must have:
* - long white (black) real body
* - no or very short upper (lower) shadow
* The meaning of "long" and "very short" is specified with TA_SetCandleSettings
* outInteger is positive (1 to 100) when white (bullish), negative (-1 to -100) when black (bearish)
*/
for i := startIdx; i < es.Len(); i++ {
if es.realBody(i) > es.average(settingBodyLong, bodyLongPeriodTotal, i) && // long body
(( // white body and very short lower shadow
es.candleColor(i) == 1 &&
es.upperShadow(i) < es.average(settingShadowVeryShort, shadowVeryShortPeriodTotal, i)) ||
( // black body and very short upper shadow
es.candleColor(i) == -1 &&
es.lowerShadow(i) < es.average(settingShadowVeryShort, shadowVeryShortPeriodTotal, i))) {
outInteger[i] = int(es.candleColor(i)) * 100
}
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
bodyLongPeriodTotal += es.rangeOf(settingBodyLong, i) -
es.rangeOf(settingBodyLong, bodyLongTrailingIdx)
shadowVeryShortPeriodTotal += es.rangeOf(settingShadowVeryShort, i) -
es.rangeOf(settingShadowVeryShort, shadowVeryShortTrailingIdx)
bodyLongTrailingIdx++
shadowVeryShortTrailingIdx++
}
return outInteger
}