mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-21 22:43:52 +00:00
types: calculate MaximumConsecutiveLosses and MaximumConsecutiveProfits
This commit is contained in:
parent
151d907457
commit
9f06be14aa
15
pkg/fixedpoint/helpers.go
Normal file
15
pkg/fixedpoint/helpers.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package fixedpoint
|
||||||
|
|
||||||
|
func Sum(values []Value) (s Value) {
|
||||||
|
s = Zero
|
||||||
|
for _, value := range values {
|
||||||
|
s = s.Add(value)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func Avg(values []Value) (avg Value) {
|
||||||
|
s := Sum(values)
|
||||||
|
avg = s.Div(NewFromInt(int64(len(values))))
|
||||||
|
return avg
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
@ -94,19 +95,42 @@ func (s IntervalProfitCollector) MarshalYAML() (interface{}, error) {
|
||||||
// TODO: Add more stats from the reference:
|
// TODO: Add more stats from the reference:
|
||||||
// See https://www.metatrader5.com/en/terminal/help/algotrading/testing_report
|
// See https://www.metatrader5.com/en/terminal/help/algotrading/testing_report
|
||||||
type TradeStats struct {
|
type TradeStats struct {
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
WinningRatio fixedpoint.Value `json:"winningRatio" yaml:"winningRatio"`
|
|
||||||
NumOfLossTrade int `json:"numOfLossTrade" yaml:"numOfLossTrade"`
|
WinningRatio fixedpoint.Value `json:"winningRatio" yaml:"winningRatio"`
|
||||||
NumOfProfitTrade int `json:"numOfProfitTrade" yaml:"numOfProfitTrade"`
|
NumOfLossTrade int `json:"numOfLossTrade" yaml:"numOfLossTrade"`
|
||||||
GrossProfit fixedpoint.Value `json:"grossProfit" yaml:"grossProfit"`
|
NumOfProfitTrade int `json:"numOfProfitTrade" yaml:"numOfProfitTrade"`
|
||||||
GrossLoss fixedpoint.Value `json:"grossLoss" yaml:"grossLoss"`
|
|
||||||
Profits []fixedpoint.Value `json:"profits" yaml:"profits"`
|
GrossProfit fixedpoint.Value `json:"grossProfit" yaml:"grossProfit"`
|
||||||
Losses []fixedpoint.Value `json:"losses" yaml:"losses"`
|
GrossLoss fixedpoint.Value `json:"grossLoss" yaml:"grossLoss"`
|
||||||
MostProfitableTrade fixedpoint.Value `json:"mostProfitableTrade" yaml:"mostProfitableTrade"`
|
|
||||||
MostLossTrade fixedpoint.Value `json:"mostLossTrade" yaml:"mostLossTrade"`
|
Profits []fixedpoint.Value `json:"profits" yaml:"profits"`
|
||||||
ProfitFactor fixedpoint.Value `json:"profitFactor" yaml:"profitFactor"`
|
Losses []fixedpoint.Value `json:"losses" yaml:"losses"`
|
||||||
TotalNetProfit fixedpoint.Value `json:"totalNetProfit" yaml:"totalNetProfit"`
|
|
||||||
IntervalProfits map[Interval]*IntervalProfitCollector `jons:"intervalProfits,omitempty" yaml: "intervalProfits,omitempty"`
|
LargestProfitTrade fixedpoint.Value `json:"largestProfitTrade,omitempty" yaml:"largestProfitTrade"`
|
||||||
|
LargestLossTrade fixedpoint.Value `json:"largestLossTrade,omitempty" yaml:"largestLossTrade"`
|
||||||
|
AverageProfitTrade fixedpoint.Value `json:"averageProfitTrade" yaml:"averageProfitTrade"`
|
||||||
|
AverageLossTrade fixedpoint.Value `json:"averageLossTrade" yaml:"averageLossTrade"`
|
||||||
|
|
||||||
|
ProfitFactor fixedpoint.Value `json:"profitFactor" yaml:"profitFactor"`
|
||||||
|
TotalNetProfit fixedpoint.Value `json:"totalNetProfit" yaml:"totalNetProfit"`
|
||||||
|
IntervalProfits map[Interval]*IntervalProfitCollector `jons:"intervalProfits,omitempty" yaml: "intervalProfits,omitempty"`
|
||||||
|
|
||||||
|
// MaximumConsecutiveWins - (counter) the longest series of winning trades
|
||||||
|
MaximumConsecutiveWins int `json:"maximumConsecutiveWins" yaml:"maximumConsecutiveWins"`
|
||||||
|
|
||||||
|
// MaximumConsecutiveLosses - (counter) the longest series of losing trades
|
||||||
|
MaximumConsecutiveLosses int `json:"maximumConsecutiveLosses" yaml:"maximumConsecutiveLosses"`
|
||||||
|
|
||||||
|
// MaximumConsecutiveProfit - ($) the longest series of winning trades and their total profit;
|
||||||
|
MaximumConsecutiveProfit fixedpoint.Value `json:"maximumConsecutiveProfit" yaml:"maximumConsecutiveProfit"`
|
||||||
|
|
||||||
|
// MaximumConsecutiveLoss - ($) the longest series of losing trades and their total loss;
|
||||||
|
MaximumConsecutiveLoss fixedpoint.Value `json:"maximumConsecutiveLoss" yaml:"maximumConsecutiveLoss"`
|
||||||
|
|
||||||
|
consecutiveSide int
|
||||||
|
consecutiveCounter int
|
||||||
|
consecutiveAmount fixedpoint.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTradeStats(symbol string) *TradeStats {
|
func NewTradeStats(symbol string) *TradeStats {
|
||||||
|
@ -119,7 +143,7 @@ func (s *TradeStats) SetIntervalProfitCollector(c *IntervalProfitCollector) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TradeStats) Add(profit *Profit) {
|
func (s *TradeStats) Add(profit *Profit) {
|
||||||
if profit.Symbol != s.Symbol {
|
if s.Symbol != "" && profit.Symbol != s.Symbol {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,12 +158,42 @@ func (s *TradeStats) add(pnl fixedpoint.Value) {
|
||||||
s.NumOfProfitTrade++
|
s.NumOfProfitTrade++
|
||||||
s.Profits = append(s.Profits, pnl)
|
s.Profits = append(s.Profits, pnl)
|
||||||
s.GrossProfit = s.GrossProfit.Add(pnl)
|
s.GrossProfit = s.GrossProfit.Add(pnl)
|
||||||
s.MostProfitableTrade = fixedpoint.Max(s.MostProfitableTrade, pnl)
|
s.LargestProfitTrade = fixedpoint.Max(s.LargestProfitTrade, pnl)
|
||||||
|
|
||||||
|
// consecutive same side (made profit last time)
|
||||||
|
if s.consecutiveSide == 0 || s.consecutiveSide == 1 {
|
||||||
|
s.consecutiveSide = 1
|
||||||
|
s.consecutiveCounter++
|
||||||
|
s.consecutiveAmount = s.consecutiveAmount.Add(pnl)
|
||||||
|
} else { // was loss, now profit, store the last loss and the loss amount
|
||||||
|
s.MaximumConsecutiveLosses = int(math.Max(float64(s.MaximumConsecutiveLosses), float64(s.consecutiveCounter)))
|
||||||
|
s.MaximumConsecutiveLoss = fixedpoint.Min(s.MaximumConsecutiveLoss, s.consecutiveAmount)
|
||||||
|
|
||||||
|
s.consecutiveSide = 1
|
||||||
|
s.consecutiveCounter = 0
|
||||||
|
s.consecutiveAmount = pnl
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
s.NumOfLossTrade++
|
s.NumOfLossTrade++
|
||||||
s.Losses = append(s.Losses, pnl)
|
s.Losses = append(s.Losses, pnl)
|
||||||
s.GrossLoss = s.GrossLoss.Add(pnl)
|
s.GrossLoss = s.GrossLoss.Add(pnl)
|
||||||
s.MostLossTrade = fixedpoint.Min(s.MostLossTrade, pnl)
|
s.LargestLossTrade = fixedpoint.Min(s.LargestLossTrade, pnl)
|
||||||
|
|
||||||
|
// consecutive same side (made loss last time)
|
||||||
|
if s.consecutiveSide == 0 || s.consecutiveSide == -1 {
|
||||||
|
s.consecutiveSide = -1
|
||||||
|
s.consecutiveCounter++
|
||||||
|
s.consecutiveAmount = s.consecutiveAmount.Add(pnl)
|
||||||
|
} else { // was profit, now loss, store the last win and profit
|
||||||
|
s.MaximumConsecutiveWins = int(math.Max(float64(s.MaximumConsecutiveWins), float64(s.consecutiveCounter)))
|
||||||
|
s.MaximumConsecutiveProfit = fixedpoint.Max(s.MaximumConsecutiveProfit, s.consecutiveAmount)
|
||||||
|
|
||||||
|
s.consecutiveSide = -1
|
||||||
|
s.consecutiveCounter = 0
|
||||||
|
s.consecutiveAmount = pnl
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
s.TotalNetProfit = s.TotalNetProfit.Add(pnl)
|
s.TotalNetProfit = s.TotalNetProfit.Add(pnl)
|
||||||
|
|
||||||
|
@ -153,22 +207,24 @@ func (s *TradeStats) add(pnl fixedpoint.Value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s.ProfitFactor = s.GrossProfit.Div(s.GrossLoss.Abs())
|
s.ProfitFactor = s.GrossProfit.Div(s.GrossLoss.Abs())
|
||||||
|
s.AverageProfitTrade = fixedpoint.Avg(s.Profits)
|
||||||
|
s.AverageLossTrade = fixedpoint.Avg(s.Losses)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output TradeStats without Profits and Losses
|
// Output TradeStats without Profits and Losses
|
||||||
func (s *TradeStats) BriefString() string {
|
func (s *TradeStats) BriefString() string {
|
||||||
out, _ := yaml.Marshal(&TradeStats{
|
out, _ := yaml.Marshal(&TradeStats{
|
||||||
Symbol: s.Symbol,
|
Symbol: s.Symbol,
|
||||||
WinningRatio: s.WinningRatio,
|
WinningRatio: s.WinningRatio,
|
||||||
NumOfLossTrade: s.NumOfLossTrade,
|
NumOfLossTrade: s.NumOfLossTrade,
|
||||||
NumOfProfitTrade: s.NumOfProfitTrade,
|
NumOfProfitTrade: s.NumOfProfitTrade,
|
||||||
GrossProfit: s.GrossProfit,
|
GrossProfit: s.GrossProfit,
|
||||||
GrossLoss: s.GrossLoss,
|
GrossLoss: s.GrossLoss,
|
||||||
MostProfitableTrade: s.MostProfitableTrade,
|
LargestProfitTrade: s.LargestProfitTrade,
|
||||||
MostLossTrade: s.MostLossTrade,
|
LargestLossTrade: s.LargestLossTrade,
|
||||||
ProfitFactor: s.ProfitFactor,
|
ProfitFactor: s.ProfitFactor,
|
||||||
TotalNetProfit: s.TotalNetProfit,
|
TotalNetProfit: s.TotalNetProfit,
|
||||||
IntervalProfits: s.IntervalProfits,
|
IntervalProfits: s.IntervalProfits,
|
||||||
})
|
})
|
||||||
return string(out)
|
return string(out)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user