-
-
Notifications
You must be signed in to change notification settings - Fork 111
/
Copy pathtrima_strategy.go
119 lines (92 loc) · 3.64 KB
/
trima_strategy.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright (c) 2021-2024 Onur Cinar.
// The source code is provided under GNU AGPLv3 License.
// https://github.com/cinar/indicator
package trend
import (
"github.com/cinar/indicator/v2/asset"
"github.com/cinar/indicator/v2/helper"
"github.com/cinar/indicator/v2/strategy"
"github.com/cinar/indicator/v2/trend"
)
const (
// DefaultTrimaStrategyShortPeriod is the first TRIMA period.
DefaultTrimaStrategyShortPeriod = 20
// DefaultTrimaStrategyLongPeriod is the second TRIMA period.
DefaultTrimaStrategyLongPeriod = 50
)
// TrimaStrategy represents the configuration parameters for calculating the TRIMA strategy.
// A bullish cross occurs when the short TRIMA moves above the long TRIMA.
// A bearish cross occurs when the short TRIMA moves below the long TRIME.
type TrimaStrategy struct {
// Trima1 represents the configuration parameters for calculating the short TRIMA.
Short *trend.Trima[float64]
// Trima2 represents the configuration parameters for calculating the long TRIMA.
Long *trend.Trima[float64]
}
// NewTrimaStrategy function initializes a new TRIMA strategy instance
// with the default parameters.
func NewTrimaStrategy() *TrimaStrategy {
t := &TrimaStrategy{
Short: trend.NewTrima[float64](),
Long: trend.NewTrima[float64](),
}
t.Short.Period = DefaultTrimaStrategyShortPeriod
t.Long.Period = DefaultTrimaStrategyLongPeriod
return t
}
// Name returns the name of the strategy.
func (*TrimaStrategy) Name() string {
return "TRIMA Strategy"
}
// Compute processes the provided asset snapshots and generates a
// stream of actionable recommendations.
func (t *TrimaStrategy) Compute(c <-chan *asset.Snapshot) <-chan strategy.Action {
closings := helper.Duplicate(asset.SnapshotsAsClosings(c), 2)
shorts := t.Short.Compute(closings[0])
longs := t.Long.Compute(closings[1])
shorts = helper.Skip(shorts, t.Long.IdlePeriod()-t.Short.IdlePeriod())
actions := helper.Operate(shorts, longs, func(short, long float64) strategy.Action {
if short > long {
return strategy.Buy
}
if long > short {
return strategy.Sell
}
return strategy.Hold
})
// TRIMA starts only after a full periods for each EMA used.
actions = helper.Shift(actions, t.Long.IdlePeriod(), strategy.Hold)
return actions
}
// Report processes the provided asset snapshots and generates a
// report annotated with the recommended actions.
func (t *TrimaStrategy) Report(c <-chan *asset.Snapshot) *helper.Report {
//
// snapshots[0] -> dates
// snapshots[1] -> closings[0] -> shorts
// closings[1] -> longs
// closings[2] -> closings
// snapshots[2] -> actions -> annotations
// -> outcomes
//
snapshots := helper.Duplicate(c, 3)
dates := asset.SnapshotsAsDates(snapshots[0])
closings := helper.Duplicate(asset.SnapshotsAsClosings(snapshots[1]), 3)
shorts := t.Short.Compute(closings[0])
longs := t.Long.Compute(closings[1])
shorts = helper.Skip(shorts, t.Long.IdlePeriod()-t.Short.IdlePeriod())
shorts = helper.Shift(shorts, t.Long.IdlePeriod(), 0)
longs = helper.Shift(longs, t.Long.IdlePeriod(), 0)
actions, outcomes := strategy.ComputeWithOutcome(t, snapshots[2])
annotations := strategy.ActionsToAnnotations(actions)
outcomes = helper.MultiplyBy(outcomes, 100)
report := helper.NewReport(t.Name(), dates)
report.AddChart()
report.AddChart()
report.AddColumn(helper.NewNumericReportColumn("Close", closings[2]))
report.AddColumn(helper.NewNumericReportColumn("Short", shorts), 1)
report.AddColumn(helper.NewNumericReportColumn("Long", longs), 1)
report.AddColumn(helper.NewAnnotationReportColumn(annotations), 0, 1)
report.AddColumn(helper.NewNumericReportColumn("Outcome", outcomes), 2)
return report
}