@@ -17,6 +17,7 @@ import (
1717 "github.com/rodrigo-brito/ninjabot/storage"
1818 "github.com/rodrigo-brito/ninjabot/strategy"
1919 "github.com/rodrigo-brito/ninjabot/tools/log"
20+ "github.com/rodrigo-brito/ninjabot/tools/metrics"
2021
2122 "github.com/olekukonko/tablewriter"
2223 "github.com/schollz/progressbar/v3"
@@ -191,20 +192,23 @@ func (n *NinjaBot) Summary() {
191192
192193 buffer := bytes .NewBuffer (nil )
193194 table := tablewriter .NewWriter (buffer )
194- table .SetHeader ([]string {"Pair" , "Trades" , "Win" , "Loss" , "% Win" , "Payoff" , "SQN" , "Profit" , "Volume" })
195+ table .SetHeader ([]string {"Pair" , "Trades" , "Win" , "Loss" , "% Win" , "Payoff" , "Pr Fact." , " SQN" , "Profit" , "Volume" })
195196 table .SetFooterAlignment (tablewriter .ALIGN_RIGHT )
196197 avgPayoff := 0.0
198+ avgProfitFactor := 0.0
197199
198200 returns := make ([]float64 , 0 )
199201 for _ , summary := range n .orderController .Results {
200202 avgPayoff += summary .Payoff () * float64 (len (summary .Win ())+ len (summary .Lose ()))
203+ avgProfitFactor += summary .ProfitFactor () * float64 (len (summary .Win ())+ len (summary .Lose ()))
201204 table .Append ([]string {
202205 summary .Pair ,
203206 strconv .Itoa (len (summary .Win ()) + len (summary .Lose ())),
204207 strconv .Itoa (len (summary .Win ())),
205208 strconv .Itoa (len (summary .Lose ())),
206209 fmt .Sprintf ("%.1f %%" , float64 (len (summary .Win ()))/ float64 (len (summary .Win ())+ len (summary .Lose ()))* 100 ),
207210 fmt .Sprintf ("%.3f" , summary .Payoff ()),
211+ fmt .Sprintf ("%.3f" , summary .ProfitFactor ()),
208212 fmt .Sprintf ("%.1f" , summary .SQN ()),
209213 fmt .Sprintf ("%.2f" , summary .Profit ()),
210214 fmt .Sprintf ("%.2f" , summary .Volume ),
@@ -226,6 +230,7 @@ func (n *NinjaBot) Summary() {
226230 strconv .Itoa (loses ),
227231 fmt .Sprintf ("%.1f %%" , float64 (wins )/ float64 (wins + loses )* 100 ),
228232 fmt .Sprintf ("%.3f" , avgPayoff / float64 (wins + loses )),
233+ fmt .Sprintf ("%.3f" , avgProfitFactor / float64 (wins + loses )),
229234 fmt .Sprintf ("%.1f" , sqn / float64 (len (n .orderController .Results ))),
230235 fmt .Sprintf ("%.2f" , total ),
231236 fmt .Sprintf ("%.2f" , volume ),
@@ -240,17 +245,44 @@ func (n *NinjaBot) Summary() {
240245 returnsPercent = append (returnsPercent , p * 100 )
241246 totalReturn += p
242247 }
243- fmt .Printf ("AVG Return: %.2f%%\n " , totalReturn / float64 (len (returns ))* 100 )
244- hist := histogram .Hist (20 , returnsPercent )
248+ hist := histogram .Hist (15 , returnsPercent )
245249 histogram .Fprint (os .Stdout , hist , histogram .Linear (10 ))
246250 fmt .Println ()
247251
252+ fmt .Println ("------ CONFIDENCE INTERVAL (95%) -------" )
253+ for pair , summary := range n .orderController .Results {
254+ fmt .Printf ("| %s |\n " , pair )
255+ returns := append (summary .WinPercent (), summary .LosePercent ()... )
256+ returnsInterval := metrics .Bootstrap (returns , metrics .Mean , 10000 , 0.95 )
257+ payoffInterval := metrics .Bootstrap (returns , metrics .Payoff , 10000 , 0.95 )
258+ profitFactorInterval := metrics .Bootstrap (returns , metrics .ProfitFactor , 10000 , 0.95 )
259+
260+ fmt .Printf ("RETURN: %.2f%% (%.2f%% ~ %.2f%%)\n " ,
261+ returnsInterval .Mean * 100 , returnsInterval .Lower * 100 , returnsInterval .Upper * 100 )
262+ fmt .Printf ("PAYOFF: %.2f (%.2f ~ %.2f)\n " ,
263+ payoffInterval .Mean , payoffInterval .Lower , payoffInterval .Upper )
264+ fmt .Printf ("PROF.FACTOR: %.2f (%.2f ~ %.2f)\n " ,
265+ profitFactorInterval .Mean , profitFactorInterval .Lower , profitFactorInterval .Upper )
266+ }
267+
268+ fmt .Println ()
269+
248270 if n .paperWallet != nil {
249271 n .paperWallet .Summary ()
250272 }
251273
252274}
253275
276+ func (n NinjaBot ) SaveReturns (outputDir string ) error {
277+ for _ , summary := range n .orderController .Results {
278+ outputFile := fmt .Sprintf ("%s/%s.csv" , outputDir , summary .Pair )
279+ if err := summary .SaveReturns (outputFile ); err != nil {
280+ return err
281+ }
282+ }
283+ return nil
284+ }
285+
254286func (n * NinjaBot ) onCandle (candle model.Candle ) {
255287 n .priorityQueueCandle .Push (candle )
256288}
0 commit comments