-
Notifications
You must be signed in to change notification settings - Fork 790
/
statistics_types.go
265 lines (239 loc) · 12.6 KB
/
statistics_types.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
package statistics
import (
"errors"
"time"
"github.com/shopspring/decimal"
"github.com/thrasher-corp/gocryptotrader/backtester/common"
"github.com/thrasher-corp/gocryptotrader/backtester/data"
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio"
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio/compliance"
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio/holdings"
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/fill"
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/order"
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/signal"
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
"github.com/thrasher-corp/gocryptotrader/common/key"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
gctkline "github.com/thrasher-corp/gocryptotrader/exchanges/kline"
gctorder "github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
var (
// ErrAlreadyProcessed occurs when an event has already been processed
ErrAlreadyProcessed = errors.New("this event has been processed already")
errExchangeAssetPairStatsUnset = errors.New("exchangeAssetPairStatistics not setup")
errCurrencyStatisticsUnset = errors.New("no data")
errMissingSnapshots = errors.New("funding report item missing USD snapshots")
errNoRelevantStatsFound = errors.New("no relevant currency pair statistics found")
errReceivedNoData = errors.New("received no data")
errNoDataAtOffset = errors.New("no data found at offset")
)
// Statistic holds all statistical information for a backtester run, from drawdowns to ratios.
// Any currency specific information is handled in currencystatistics
type Statistic struct {
StrategyName string `json:"strategy-name"`
StrategyDescription string `json:"strategy-description"`
StrategyNickname string `json:"strategy-nickname"`
StrategyGoal string `json:"strategy-goal"`
StartDate time.Time `json:"start-date"`
EndDate time.Time `json:"end-date"`
CandleInterval gctkline.Interval `json:"candle-interval"`
RiskFreeRate decimal.Decimal `json:"risk-free-rate"`
ExchangeAssetPairStatistics map[key.ExchangePairAsset]*CurrencyPairStatistic `json:"-"`
CurrencyStatistics []*CurrencyPairStatistic `json:"currency-statistics"`
TotalBuyOrders int64 `json:"total-buy-orders"`
TotalLongOrders int64 `json:"total-long-orders"`
TotalShortOrders int64 `json:"total-short-orders"`
TotalSellOrders int64 `json:"total-sell-orders"`
TotalOrders int64 `json:"total-orders"`
BiggestDrawdown *FinalResultsHolder `json:"biggest-drawdown,omitempty"`
BestStrategyResults *FinalResultsHolder `json:"best-start-results,omitempty"`
BestMarketMovement *FinalResultsHolder `json:"best-market-movement,omitempty"`
WasAnyDataMissing bool `json:"was-any-data-missing"`
FundingStatistics *FundingStatistics `json:"funding-statistics"`
FundManager funding.IFundingManager `json:"-"`
HasCollateral bool `json:"has-collateral"`
}
// FinalResultsHolder holds important stats about a currency's performance
type FinalResultsHolder struct {
Exchange string `json:"exchange"`
Asset asset.Item `json:"asset"`
Pair currency.Pair `json:"currency"`
MaxDrawdown Swing `json:"max-drawdown"`
MarketMovement decimal.Decimal `json:"market-movement"`
StrategyMovement decimal.Decimal `json:"strategy-movement"`
}
// Handler interface details what a statistic is expected to do
type Handler interface {
SetStrategyName(string)
SetEventForOffset(common.Event) error
AddHoldingsForTime(*holdings.Holding) error
AddComplianceSnapshotForTime(*compliance.Snapshot, common.Event) error
CalculateAllResults() error
Reset() error
Serialise() (string, error)
AddPNLForTime(*portfolio.PNLSummary) error
CreateLog(common.Event) (string, error)
}
// Results holds some statistics on results
type Results struct {
Pair string `json:"pair"`
TotalEvents int `json:"totalEvents"`
TotalTransactions int `json:"totalTransactions"`
Events []ResultEvent `json:"events"`
Transactions []ResultTransactions `json:"transactions"`
StrategyName string `json:"strategyName"`
}
// ResultTransactions stores details on a transaction
type ResultTransactions struct {
Time time.Time `json:"time"`
Direction gctorder.Side `json:"direction"`
Price decimal.Decimal `json:"price"`
Amount decimal.Decimal `json:"amount"`
Reason string `json:"reason,omitempty"`
}
// ResultEvent stores the time
type ResultEvent struct {
Time time.Time `json:"time"`
}
type eventOutputHolder struct {
Time time.Time
Events []string
}
// CurrencyStats defines what is expected in order to
// calculate statistics based on an exchange, asset type and currency pair
type CurrencyStats interface {
TotalEquityReturn() (decimal.Decimal, error)
MaxDrawdown() Swing
LongestDrawdown() Swing
SharpeRatio(decimal.Decimal) decimal.Decimal
SortinoRatio(decimal.Decimal) decimal.Decimal
}
// DataAtOffset is used to hold all event information
// at a time interval
type DataAtOffset struct {
Offset int64
ClosePrice decimal.Decimal
Time time.Time
Holdings holdings.Holding
ComplianceSnapshot *compliance.Snapshot
DataEvent data.Event
SignalEvent signal.Event
OrderEvent order.Event
FillEvent fill.Event
PNL portfolio.IPNL
}
// CurrencyPairStatistic Holds all events and statistics relevant to an exchange, asset type and currency pair
type CurrencyPairStatistic struct {
Exchange string
Asset asset.Item
Currency currency.Pair
UnderlyingPair currency.Pair `json:"linked-spot-currency"`
ShowMissingDataWarning bool `json:"-"`
IsStrategyProfitable bool `json:"is-strategy-profitable"`
DoesPerformanceBeatTheMarket bool `json:"does-performance-beat-the-market"`
BuyOrders int64 `json:"buy-orders"`
SellOrders int64 `json:"sell-orders"`
TotalOrders int64 `json:"total-orders"`
StartingClosePrice ValueAtTime `json:"starting-close-price"`
EndingClosePrice ValueAtTime `json:"ending-close-price"`
LowestClosePrice ValueAtTime `json:"lowest-close-price"`
HighestClosePrice ValueAtTime `json:"highest-close-price"`
HighestUnrealisedPNL ValueAtTime `json:"highest-unrealised-pnl"`
LowestUnrealisedPNL ValueAtTime `json:"lowest-unrealised-pnl"`
HighestRealisedPNL ValueAtTime `json:"highest-realised-pnl"`
LowestRealisedPNL ValueAtTime `json:"lowest-realised-pnl"`
MarketMovement decimal.Decimal `json:"market-movement"`
StrategyMovement decimal.Decimal `json:"strategy-movement"`
UnrealisedPNL decimal.Decimal `json:"unrealised-pnl"`
RealisedPNL decimal.Decimal `json:"realised-pnl"`
CompoundAnnualGrowthRate decimal.Decimal `json:"compound-annual-growth-rate"`
TotalAssetValue decimal.Decimal `json:"total-asset-value"`
TotalFees decimal.Decimal `json:"total-fees"`
TotalValueLostToVolumeSizing decimal.Decimal `json:"total-value-lost-to-volume-sizing"`
TotalValueLostToSlippage decimal.Decimal `json:"total-value-lost-to-slippage"`
TotalValueLost decimal.Decimal `json:"total-value-lost"`
Events []DataAtOffset `json:"-"`
MaxDrawdown Swing `json:"max-drawdown,omitempty"`
HighestCommittedFunds ValueAtTime `json:"highest-committed-funds"`
GeometricRatios *Ratios `json:"geometric-ratios"`
ArithmeticRatios *Ratios `json:"arithmetic-ratios"`
InitialHoldings holdings.Holding `json:"initial-holdings-holdings"`
FinalHoldings holdings.Holding `json:"final-holdings"`
FinalOrders compliance.Snapshot `json:"final-orders"`
}
// Ratios stores all the ratios used for statistics
type Ratios struct {
SharpeRatio decimal.Decimal `json:"sharpe-ratio"`
SortinoRatio decimal.Decimal `json:"sortino-ratio"`
InformationRatio decimal.Decimal `json:"information-ratio"`
CalmarRatio decimal.Decimal `json:"calmar-ratio"`
}
// Swing holds a drawdown
type Swing struct {
Highest ValueAtTime `json:"highest"`
Lowest ValueAtTime `json:"lowest"`
DrawdownPercent decimal.Decimal `json:"drawdown"`
IntervalDuration int64 `json:"interval-duration"`
}
// ValueAtTime is an individual iteration of price at a time
type ValueAtTime struct {
Time time.Time `json:"time"`
Value decimal.Decimal `json:"value"`
Set bool `json:"-"`
}
type relatedCurrencyPairStatistics struct {
isBaseCurrency bool
stat *CurrencyPairStatistic
}
// FundingStatistics stores all funding related statistics
type FundingStatistics struct {
Report *funding.Report `json:"-"`
Items []FundingItemStatistics `json:"funding-item-statistics"`
TotalUSDStatistics *TotalFundingStatistics `json:"total-usd-statistics"`
}
// FundingItemStatistics holds statistics for funding items
type FundingItemStatistics struct {
ReportItem *funding.ReportItem `json:"-"`
// USD stats
StartingClosePrice ValueAtTime `json:"starting-close-price"`
EndingClosePrice ValueAtTime `json:"ending-close-price"`
LowestClosePrice ValueAtTime `json:"lowest-close-price"`
HighestClosePrice ValueAtTime `json:"highest-close-price"`
MarketMovement decimal.Decimal `json:"market-movement"`
StrategyMovement decimal.Decimal `json:"strategy-movement"`
DidStrategyBeatTheMarket bool `json:"did-strategy-beat-the-market"`
RiskFreeRate decimal.Decimal `json:"risk-free-rate"`
CompoundAnnualGrowthRate decimal.Decimal `json:"compound-annual-growth-rate"`
BuyOrders int64 `json:"buy-orders"`
SellOrders int64 `json:"sell-orders"`
TotalOrders int64 `json:"total-orders"`
MaxDrawdown Swing `json:"max-drawdown"`
HighestCommittedFunds ValueAtTime `json:"highest-committed-funds"`
// CollateralPair stats
IsCollateral bool `json:"is-collateral"`
InitialCollateral ValueAtTime `json:"initial-collateral"`
FinalCollateral ValueAtTime `json:"final-collateral"`
HighestCollateral ValueAtTime `json:"highest-collateral"`
LowestCollateral ValueAtTime `json:"lowest-collateral"`
// Contracts
LowestHoldings ValueAtTime `json:"lowest-holdings"`
HighestHoldings ValueAtTime `json:"highest-holdings"`
InitialHoldings ValueAtTime `json:"initial-holdings"`
FinalHoldings ValueAtTime `json:"final-holdings"`
}
// TotalFundingStatistics holds values for overall statistics for funding items
type TotalFundingStatistics struct {
HoldingValues []ValueAtTime `json:"-"`
HighestHoldingValue ValueAtTime `json:"highest-holding-value"`
LowestHoldingValue ValueAtTime `json:"lowest-holding-value"`
BenchmarkMarketMovement decimal.Decimal `json:"benchmark-market-movement"`
RiskFreeRate decimal.Decimal `json:"risk-free-rate"`
CompoundAnnualGrowthRate decimal.Decimal `json:"compound-annual-growth-rate"`
MaxDrawdown Swing `json:"max-drawdown"`
GeometricRatios *Ratios `json:"geometric-ratios"`
ArithmeticRatios *Ratios `json:"arithmetic-ratios"`
DidStrategyBeatTheMarket bool `json:"did-strategy-beat-the-market"`
DidStrategyMakeProfit bool `json:"did-strategy-make-profit"`
HoldingValueDifference decimal.Decimal `json:"holding-value-difference"`
}