-
Notifications
You must be signed in to change notification settings - Fork 2
/
session.go
186 lines (152 loc) · 4.07 KB
/
session.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package gotrader
import (
"errors"
"github.com/sirupsen/logrus"
)
// Option represents trading session functional option
type Option func(p *sessionParameters)
// Instruments is the functional option to define the instruments to trade
func Instruments(instruments []string) Option {
return func(p *sessionParameters) {
p.instruments = instruments
}
}
// AccountID is the functional option to define the account where the session will operate
func AccountID(account string) Option {
return func(p *sessionParameters) {
p.account = account
}
}
// HedgeType is the functional option to choose how hedge is calculated in the backtest engine.
func HedgeType(hedge Hedge) Option {
return func(p *sessionParameters) {
if p.testParameters != nil {
p.testParameters.hedge = hedge
} else {
p.testParameters = &testParameters{
hedge: hedge,
}
}
}
}
// InitialBalance is the functional option to define the initial balance in the backtest engine.
func InitialBalance(value float64) Option {
return func(p *sessionParameters) {
if p.testParameters != nil {
p.testParameters.initialBalance = value
} else {
p.testParameters = &testParameters{
initialBalance: value,
}
}
}
}
// HomeCurrency is the functional option to define home currency in the backtest engine.
func HomeCurrency(ccy string) Option {
return func(p *sessionParameters) {
if p.testParameters != nil {
p.testParameters.homeCurrency = ccy
} else {
p.testParameters = &testParameters{
homeCurrency: ccy,
}
}
}
}
// Leverage is the functional option to define account leverage in the backtest engine.
func Leverage(leverage float64) Option {
return func(p *sessionParameters) {
if p.testParameters != nil {
p.testParameters.leverage = leverage
} else {
p.testParameters = &testParameters{
leverage: leverage,
}
}
}
}
// SetLogger is the functional option to define which logger will be used by the engine.
func SetLogger(logger Logger) Option {
return func(p *sessionParameters) {
p.logger = logger
}
}
type testParameters struct {
initialBalance float64
homeCurrency string
leverage float64
hedge Hedge
}
type sessionParameters struct {
instruments []string
account string
testParameters *testParameters
logger Logger
}
// TradingSession represents the entrypoint struct of the gotrader package, representing a trading session.
type TradingSession struct {
strategy Strategy
engine Engine
client BrokerClient
parameters *sessionParameters
engineType int
}
// NewTradingSession is the TradingSession constructor.
func NewTradingSession(opts ...Option) *TradingSession {
params := &sessionParameters{}
for _, o := range opts {
o(params)
}
return &TradingSession{
parameters: params,
}
}
// SetStrategy sets the strategy to trade.
func (s *TradingSession) SetStrategy(strategy Strategy) *TradingSession {
s.strategy = strategy
return s
}
// SetClient sets the client that will be used for comunication with the broker.
func (s *TradingSession) SetClient(client BrokerClient) *TradingSession {
s.client = client
return s
}
// Live defines that this is a live session.
func (s *TradingSession) Live() *TradingSession {
if s.parameters.logger == nil {
s.parameters.logger = logrus.New()
}
s.engine = newLiveEngine(s.parameters.logger)
return s
}
// Backtest defines that this is a backtesting session.
func (s *TradingSession) Backtest() *TradingSession {
if s.parameters.logger == nil {
s.parameters.logger = logrus.New()
}
s.engine = newBtEngine(s.parameters.logger)
s.engineType = 1
return s
}
// Start trading session.
func (s *TradingSession) Start() error {
if s.engine == nil {
return errors.New("engine type is not defined")
}
var err error
switch s.engineType {
case 0:
engine := s.engine.(*liveEngine)
engine.client = s.client
engine.strategy = s.strategy
engine.parameters = s.parameters
err = engine.start()
case 1:
engine := s.engine.(*btEngine)
engine.client = s.client
engine.strategy = s.strategy
engine.parameters = s.parameters
err = engine.start()
}
return err
}