54
54
'technology' ]
55
55
}
56
56
57
+ BENCHMARK_RETS_WARNING = ('The latest version of pyfolio requires users to '
58
+ 'supply benchmark returns. Your current tearsheets '
59
+ 'will not include plots and analyses that require a '
60
+ 'benchmark. In the future, please pass '
61
+ 'benchmark_rets, or pass None to silence this '
62
+ 'warning.' )
63
+
57
64
58
65
def timer (msg_body , previous_time ):
59
66
current_time = time ()
@@ -68,7 +75,7 @@ def create_full_tear_sheet(returns,
68
75
positions = None ,
69
76
transactions = None ,
70
77
market_data = None ,
71
- benchmark_rets = None ,
78
+ benchmark_rets = utils . NOT_PASSED_SENTINEL ,
72
79
slippage = None ,
73
80
live_start_date = None ,
74
81
sector_mappings = None ,
@@ -188,6 +195,10 @@ def create_full_tear_sheet(returns,
188
195
factor returns and risk exposures plots
189
196
- See create_perf_attrib_tear_sheet().
190
197
"""
198
+ if (isinstance (benchmark_rets , str )
199
+ and benchmark_rets == utils .NOT_PASSED_SENTINEL ):
200
+ warnings .warn (BENCHMARK_RETS_WARNING )
201
+ benchmark_rets = None
191
202
192
203
if (unadjusted_returns is None ) and (slippage is not None ) and \
193
204
(transactions is not None ):
@@ -262,7 +273,7 @@ def create_full_tear_sheet(returns,
262
273
def create_simple_tear_sheet (returns ,
263
274
positions = None ,
264
275
transactions = None ,
265
- benchmark_rets = None ,
276
+ benchmark_rets = utils . NOT_PASSED_SENTINEL ,
266
277
slippage = None ,
267
278
estimate_intraday = 'infer' ,
268
279
live_start_date = None ,
@@ -335,6 +346,11 @@ def create_simple_tear_sheet(returns,
335
346
positions = utils .check_intraday (estimate_intraday , returns ,
336
347
positions , transactions )
337
348
349
+ if (isinstance (benchmark_rets , str )
350
+ and benchmark_rets == utils .NOT_PASSED_SENTINEL ):
351
+ warnings .warn (BENCHMARK_RETS_WARNING )
352
+ benchmark_rets = None
353
+
338
354
if (slippage is not None ) and (transactions is not None ):
339
355
returns = txn .adjust_returns_for_slippage (returns , positions ,
340
356
transactions , slippage )
@@ -443,7 +459,7 @@ def create_returns_tear_sheet(returns, positions=None,
443
459
transactions = None ,
444
460
live_start_date = None ,
445
461
cone_std = (1.0 , 1.5 , 2.0 ),
446
- benchmark_rets = None ,
462
+ benchmark_rets = utils . NOT_PASSED_SENTINEL ,
447
463
bootstrap = False ,
448
464
turnover_denom = 'AGB' ,
449
465
header_rows = None ,
@@ -493,6 +509,11 @@ def create_returns_tear_sheet(returns, positions=None,
493
509
If True, returns the figure that was plotted on.
494
510
"""
495
511
512
+ if (isinstance (benchmark_rets , str )
513
+ and benchmark_rets == utils .NOT_PASSED_SENTINEL ):
514
+ warnings .warn (BENCHMARK_RETS_WARNING )
515
+ benchmark_rets = None
516
+
496
517
if benchmark_rets is not None :
497
518
returns = utils .clip_returns_to_benchmark (returns , benchmark_rets )
498
519
@@ -506,18 +527,21 @@ def create_returns_tear_sheet(returns, positions=None,
506
527
507
528
plotting .show_worst_drawdown_periods (returns )
508
529
509
- vertical_sections = 11
530
+ always_sections = 11
531
+ live_start_date_sections = 1 if (live_start_date is not None ) else 0
532
+ benchmark_sections = 1 if (benchmark_rets is not None ) else 0
533
+ bootstrap_sections = 1 if bootstrap else 0
534
+
535
+ vertical_sections = sum ([
536
+ always_sections ,
537
+ live_start_date_sections ,
538
+ benchmark_sections ,
539
+ bootstrap_sections
540
+ ])
510
541
511
542
if live_start_date is not None :
512
- vertical_sections += 1
513
543
live_start_date = ep .utils .get_utc_timestamp (live_start_date )
514
544
515
- if benchmark_rets is not None :
516
- vertical_sections += 1
517
-
518
- if bootstrap :
519
- vertical_sections += 1
520
-
521
545
fig = plt .figure (figsize = (14 , vertical_sections * 6 ))
522
546
gs = gridspec .GridSpec (vertical_sections , 3 , wspace = 0.5 , hspace = 0.5 )
523
547
ax_rolling_returns = plt .subplot (gs [:2 , :])
@@ -531,10 +555,10 @@ def create_returns_tear_sheet(returns, positions=None,
531
555
i += 1
532
556
ax_returns = plt .subplot (gs [i , :],
533
557
sharex = ax_rolling_returns )
534
- i += 1
535
558
if benchmark_rets is not None :
536
- ax_rolling_beta = plt .subplot (gs [i , :], sharex = ax_rolling_returns )
537
559
i += 1
560
+ ax_rolling_beta = plt .subplot (gs [i , :], sharex = ax_rolling_returns )
561
+ i += 1
538
562
ax_rolling_volatility = plt .subplot (gs [i , :], sharex = ax_rolling_returns )
539
563
i += 1
540
564
ax_rolling_sharpe = plt .subplot (gs [i , :], sharex = ax_rolling_returns )
@@ -614,7 +638,8 @@ def create_returns_tear_sheet(returns, positions=None,
614
638
live_start_date = live_start_date ,
615
639
ax = ax_return_quantiles )
616
640
617
- if bootstrap and benchmark_rets is not None :
641
+ if ((bootstrap is not None )
642
+ and (benchmark_rets is not None )):
618
643
ax_bootstrap = plt .subplot (gs [i , :])
619
644
plotting .plot_perf_stats (returns , benchmark_rets ,
620
645
ax = ax_bootstrap )
@@ -907,7 +932,10 @@ def create_round_trip_tear_sheet(returns, positions, transactions,
907
932
908
933
@plotting .customize
909
934
def create_interesting_times_tear_sheet (
910
- returns , benchmark_rets = None , legend_loc = 'best' , return_fig = False ):
935
+ returns ,
936
+ benchmark_rets = utils .NOT_PASSED_SENTINEL ,
937
+ legend_loc = 'best' ,
938
+ return_fig = False ):
911
939
"""
912
940
Generate a number of returns plots around interesting points in time,
913
941
like the flash crash and 9/11.
@@ -934,6 +962,11 @@ def create_interesting_times_tear_sheet(
934
962
If True, returns the figure that was plotted on.
935
963
"""
936
964
965
+ if (isinstance (benchmark_rets , str )
966
+ and benchmark_rets == utils .NOT_PASSED_SENTINEL ):
967
+ warnings .warn (BENCHMARK_RETS_WARNING )
968
+ benchmark_rets = None
969
+
937
970
rets_interesting = timeseries .extract_interesting_date_ranges (returns )
938
971
939
972
if not rets_interesting :
@@ -1094,7 +1127,8 @@ def create_capacity_tear_sheet(returns, positions, transactions,
1094
1127
1095
1128
1096
1129
@plotting .customize
1097
- def create_bayesian_tear_sheet (returns , benchmark_rets = None ,
1130
+ def create_bayesian_tear_sheet (returns ,
1131
+ benchmark_rets = utils .NOT_PASSED_SENTINEL ,
1098
1132
live_start_date = None , samples = 2000 ,
1099
1133
return_fig = False , stoch_vol = False ,
1100
1134
progressbar = True ):
@@ -1126,6 +1160,10 @@ def create_bayesian_tear_sheet(returns, benchmark_rets=None,
1126
1160
progressbar : boolean, optional
1127
1161
If True, show a progress bar
1128
1162
"""
1163
+ if (isinstance (benchmark_rets , str )
1164
+ and benchmark_rets == utils .NOT_PASSED_SENTINEL ):
1165
+ warnings .warn (BENCHMARK_RETS_WARNING )
1166
+ benchmark_rets = None
1129
1167
1130
1168
if not have_bayesian :
1131
1169
raise NotImplementedError (
0 commit comments