aplotly 1.1.23__tar.gz → 1.1.25__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. {aplotly-1.1.23/aplotly.egg-info → aplotly-1.1.25}/PKG-INFO +1 -1
  2. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly/colors.py +28 -1
  3. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly/plots.py +113 -33
  4. {aplotly-1.1.23 → aplotly-1.1.25/aplotly.egg-info}/PKG-INFO +1 -1
  5. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_lines.py +5 -4
  6. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_multiple_performance.py +1 -0
  7. {aplotly-1.1.23 → aplotly-1.1.25}/pyproject.toml +2 -2
  8. {aplotly-1.1.23 → aplotly-1.1.25}/LICENSE +0 -0
  9. {aplotly-1.1.23 → aplotly-1.1.25}/MANIFEST.in +0 -0
  10. {aplotly-1.1.23 → aplotly-1.1.25}/README.md +0 -0
  11. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly/__init__.py +0 -0
  12. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly/io.py +0 -0
  13. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly/style.py +0 -0
  14. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly/utils/return_breakdown.py +0 -0
  15. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly.egg-info/SOURCES.txt +0 -0
  16. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly.egg-info/dependency_links.txt +0 -0
  17. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly.egg-info/requires.txt +0 -0
  18. {aplotly-1.1.23 → aplotly-1.1.25}/aplotly.egg-info/top_level.txt +0 -0
  19. {aplotly-1.1.23 → aplotly-1.1.25}/examples/fetch_deribit_data.py +0 -0
  20. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_bars.py +0 -0
  21. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_confidence_interval.py +0 -0
  22. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_correlation.py +0 -0
  23. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_exposure_tree.py +0 -0
  24. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_gauge.py +0 -0
  25. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_line.py +0 -0
  26. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_line_and_save.py +0 -0
  27. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_lines_with_dist.py +0 -0
  28. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_market.py +0 -0
  29. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_participation.py +0 -0
  30. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_performance.py +0 -0
  31. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_performance_by_trade.py +0 -0
  32. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_return_side.py +0 -0
  33. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_returns_breakdown.py +0 -0
  34. {aplotly-1.1.23 → aplotly-1.1.25}/examples/plot_returns_tree.py +0 -0
  35. {aplotly-1.1.23 → aplotly-1.1.25}/setup.cfg +0 -0
  36. {aplotly-1.1.23 → aplotly-1.1.25}/tests/test_colors.py +0 -0
  37. {aplotly-1.1.23 → aplotly-1.1.25}/tests/test_io.py +0 -0
  38. {aplotly-1.1.23 → aplotly-1.1.25}/tests/test_style.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aplotly
3
- Version: 1.1.23
3
+ Version: 1.1.25
4
4
  License: MIT License
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -126,8 +126,30 @@ def dark_mode():
126
126
  return line_colors, chart_colors
127
127
 
128
128
 
129
+ def contrast():
130
+ line_colors = {
131
+ "orange": "#F26451",
132
+ "yellow": "#FFD700",
133
+ "purple": "#9B4F96",
134
+ "teal": "#2A9D8F",
135
+ "indigo": "#4B0082",
136
+ "grey": "#CCCCCC",
137
+ "blue": "#00BFFF",
138
+ "mint": "#98FF98",
139
+ }
140
+
141
+ chart_colors = {
142
+ "background": "#000000",
143
+ "grid": "#333333",
144
+ "text": "#E5E5E5",
145
+ "axes": "#E5E5E5",
146
+ }
147
+
148
+ return line_colors, chart_colors
149
+
150
+
129
151
  def available_palettes():
130
- return ["default", "greys", "night", "dark_mode"]
152
+ return ["default", "greys", "night", "dark_mode", "contrast"]
131
153
 
132
154
 
133
155
  def select_palette(name, color_type="hex") -> Tuple[dict, dict]:
@@ -167,5 +189,10 @@ def select_palette(name, color_type="hex") -> Tuple[dict, dict]:
167
189
  return convert_palette_to_rgba(dark_mode()[0]), convert_palette_to_rgba(dark_mode()[1])
168
190
  else:
169
191
  return dark_mode()
192
+ elif name == "contrast":
193
+ if color_type == "rgba":
194
+ return convert_palette_to_rgba(contrast()[0]), convert_palette_to_rgba(contrast()[1])
195
+ else:
196
+ return contrast()
170
197
  else:
171
198
  raise ValueError("palette name not found")
@@ -119,6 +119,7 @@ def plot_multiple_lines(
119
119
  color_palette: str = "",
120
120
  group_title: str = "",
121
121
  plot_title: str = "",
122
+ fade_secondary_lines: bool = False,
122
123
  ) -> go.Figure:
123
124
  """Plot multiple line charts.
124
125
 
@@ -134,6 +135,7 @@ def plot_multiple_lines(
134
135
  color_palette (str, optional): name of the color palette to use. Defaults to "" (default color palette).
135
136
  group_title (str, optional): name of the legend group. Defaults to "" (no group name).
136
137
  plot_title (str, optional): title for the plot. Defaults to "" (no title).
138
+ fade_secondary_lines (bool, optional): if True, all lines after the first one will have 40% transparency. Defaults to False.
137
139
 
138
140
  Returns:
139
141
  go.Figure: plotly figure containing the line charts.
@@ -155,11 +157,41 @@ def plot_multiple_lines(
155
157
 
156
158
  configure_plotly(subplots=1, color_palette=color_palette)
157
159
  fig = go.Figure()
158
- for data, label, visibility, style, color in zip(series, labels, visible, styles, colors):
160
+
161
+ # Plot first line first with Scattergl
162
+ if series and labels and visible and styles and colors:
163
+ if colors[0] is not None:
164
+ styles[0] = styles[0].copy() if styles[0] is not None else {}
165
+ styles[0]["color"] = colors[0]
166
+
167
+ fig.add_trace(
168
+ go.Scattergl(
169
+ x=series[0].index,
170
+ y=series[0].values,
171
+ mode="lines",
172
+ name=labels[0],
173
+ legendgroup=1,
174
+ legendgrouptitle_text=group_title,
175
+ visible=visible[0],
176
+ line=styles[0],
177
+ opacity=1.0,
178
+ )
179
+ )
180
+
181
+ # Update colors to ensure consistency
182
+ fig.for_each_trace(lambda trace: trace.update(line=dict(color=trace.marker.color)))
183
+
184
+ # Plot secondary lines after
185
+ for i, (data, label, visibility, style, color) in enumerate(
186
+ zip(series[1:], labels[1:], visible[1:], styles[1:], colors[1:])
187
+ ):
159
188
  if color is not None:
160
189
  style = style.copy() if style is not None else {}
161
190
  style["color"] = color
162
-
191
+
192
+ # Set opacity based on whether this is the first line and if fading is enabled
193
+ opacity = 0.4 if fade_secondary_lines else 1.0
194
+
163
195
  fig.add_trace(
164
196
  go.Scatter(
165
197
  x=data.index,
@@ -170,8 +202,10 @@ def plot_multiple_lines(
170
202
  legendgrouptitle_text=group_title,
171
203
  visible=visibility,
172
204
  line=style,
205
+ opacity=opacity,
173
206
  )
174
207
  )
208
+
175
209
  fig.update_xaxes(title_text=xlabel)
176
210
  fig.update_yaxes(title_text=ylabel)
177
211
  fig.update_layout(showlegend=legend, title_text=plot_title)
@@ -410,6 +444,7 @@ def plot_multiple_performance(
410
444
  row_heights: list = [0.7, 0.3],
411
445
  vertical_spacing: float = 0.02,
412
446
  plot_title: str = "",
447
+ fade_secondary_lines: bool = True,
413
448
  ) -> go.Figure:
414
449
  """Plot the performance and drawdown of multiple strategies.
415
450
 
@@ -429,6 +464,7 @@ def plot_multiple_performance(
429
464
  row_heights (list, optional): height of each row. Defaults to [0.7, 0.3].
430
465
  vertical_spacing (float, optional): vertical spacing between rows. Defaults to 0.02.
431
466
  plot_title (str, optional): title for the plot. Defaults to "" (no title).
467
+ fade_secondary_lines (bool, optional): if True, all lines after the first one will have 40% transparency. Defaults to True.
432
468
 
433
469
  Returns:
434
470
  go.Figure: plotly figure containing the performance and drawdown.
@@ -442,9 +478,48 @@ def plot_multiple_performance(
442
478
 
443
479
  configure_plotly(subplots=2, color_palette=color_palette)
444
480
  fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=vertical_spacing, row_heights=row_heights)
445
- for _performance, _drawdown, label in zip(performance, drawdown, labels):
481
+
482
+ # Plot first line first
483
+ if performance and drawdown and labels:
484
+ fig.add_trace(
485
+ go.Scatter(
486
+ x=performance[0].index,
487
+ y=performance[0],
488
+ mode="lines",
489
+ name=labels[0],
490
+ legendgroup=1,
491
+ legendgrouptitle_text=performance_group_title,
492
+ line=dict(width=2),
493
+ opacity=1.0,
494
+ ),
495
+ row=1,
496
+ col=1,
497
+ )
498
+
499
+ fig.for_each_trace(lambda trace: trace.update(line=dict(color=trace.marker.color)))
500
+
446
501
  fig.add_trace(
447
502
  go.Scatter(
503
+ x=drawdown[0].index,
504
+ y=drawdown[0],
505
+ mode="lines",
506
+ name=labels[0],
507
+ legendgroup=2,
508
+ legendgrouptitle_text=drawdown_group_title,
509
+ line=dict(width=2),
510
+ opacity=1.0,
511
+ ),
512
+ row=2,
513
+ col=1,
514
+ )
515
+
516
+ # Plot secondary lines using Scattergl to ensure they're on top
517
+ for i, (_performance, _drawdown, label) in enumerate(zip(performance[1:], drawdown[1:], labels[1:])):
518
+ # Set opacity based on whether this is the first line and if transparency is enabled
519
+ opacity = 0.4 if fade_secondary_lines else 1.0
520
+
521
+ fig.add_trace(
522
+ go.Scattergl(
448
523
  x=_performance.index,
449
524
  y=_performance,
450
525
  mode="lines",
@@ -452,6 +527,7 @@ def plot_multiple_performance(
452
527
  legendgroup=1,
453
528
  legendgrouptitle_text=performance_group_title,
454
529
  line=dict(width=2),
530
+ opacity=opacity,
455
531
  ),
456
532
  row=1,
457
533
  col=1,
@@ -460,7 +536,7 @@ def plot_multiple_performance(
460
536
  fig.for_each_trace(lambda trace: trace.update(line=dict(color=trace.marker.color)))
461
537
 
462
538
  fig.add_trace(
463
- go.Scatter(
539
+ go.Scattergl(
464
540
  x=_drawdown.index,
465
541
  y=_drawdown,
466
542
  mode="lines",
@@ -468,6 +544,7 @@ def plot_multiple_performance(
468
544
  legendgroup=2,
469
545
  legendgrouptitle_text=drawdown_group_title,
470
546
  line=dict(width=2),
547
+ opacity=opacity,
471
548
  ),
472
549
  row=2,
473
550
  col=1,
@@ -1125,7 +1202,7 @@ def plot_benchmark_portfolio_returns(
1125
1202
  portfolio_name: str = "Portfolio",
1126
1203
  ) -> go.Figure:
1127
1204
  """Plot a double bar chart showing benchmark returns and portfolio returns for either positive or negative months.
1128
-
1205
+
1129
1206
  Args:
1130
1207
  benchmark_returns (pd.Series): Series containing benchmark returns data.
1131
1208
  portfolio_returns (pd.Series): Series containing portfolio returns data.
@@ -1134,23 +1211,23 @@ def plot_benchmark_portfolio_returns(
1134
1211
  plot_title (str, optional): Title for the plot. Defaults to None (no title).
1135
1212
  benchmark_name (str, optional): Name of the benchmark for display. Defaults to "Benchmark".
1136
1213
  portfolio_name (str, optional): Name of the portfolio for display. Defaults to "Portfolio".
1137
-
1214
+
1138
1215
  Returns:
1139
1216
  go.Figure: Plotly figure containing the double bar chart.
1140
1217
  """
1141
1218
  # Configure plotly style
1142
1219
  configure_plotly(subplots=2, color_palette=color_palette)
1143
-
1220
+
1144
1221
  # Create subplot with shared x-axis and small gap
1145
1222
  fig = make_subplots(
1146
- rows=2,
1147
- cols=1,
1148
- shared_xaxes=True,
1223
+ rows=2,
1224
+ cols=1,
1225
+ shared_xaxes=True,
1149
1226
  vertical_spacing=0.05, # Add small gap between plots
1150
1227
  row_heights=[0.5, 0.5],
1151
- subplot_titles=("", "") # Remove subplot titles from top
1228
+ subplot_titles=("", ""), # Remove subplot titles from top
1152
1229
  )
1153
-
1230
+
1154
1231
  # Filter for positive or negative months based on benchmark returns
1155
1232
  if positive_months:
1156
1233
  filtered_months = benchmark_returns[benchmark_returns > 0].index
@@ -1158,16 +1235,16 @@ def plot_benchmark_portfolio_returns(
1158
1235
  else:
1159
1236
  filtered_months = benchmark_returns[benchmark_returns < 0].index
1160
1237
  title_suffix = "Negative"
1161
-
1238
+
1162
1239
  # Get the filtered data
1163
1240
  filtered_benchmark = benchmark_returns.loc[filtered_months]
1164
1241
  filtered_portfolio = portfolio_returns.loc[filtered_months]
1165
-
1242
+
1166
1243
  # Define colors
1167
1244
  benchmark_color = "orange"
1168
1245
  portfolio_color = "blue"
1169
1246
  portfolio_negative_color = "darkblue" # Darker blue for negative portfolio returns
1170
-
1247
+
1171
1248
  # Add benchmark returns bar chart
1172
1249
  fig.add_trace(
1173
1250
  go.Bar(
@@ -1176,13 +1253,14 @@ def plot_benchmark_portfolio_returns(
1176
1253
  name=f"{benchmark_name} Returns",
1177
1254
  marker_color=benchmark_color,
1178
1255
  ),
1179
- row=1, col=1
1256
+ row=1,
1257
+ col=1,
1180
1258
  )
1181
-
1259
+
1182
1260
  # Split portfolio returns into positive and negative for different colors
1183
1261
  positive_portfolio = filtered_portfolio[filtered_portfolio > 0]
1184
1262
  negative_portfolio = filtered_portfolio[filtered_portfolio < 0]
1185
-
1263
+
1186
1264
  # Add positive portfolio returns bar chart
1187
1265
  if not positive_portfolio.empty:
1188
1266
  fig.add_trace(
@@ -1192,9 +1270,10 @@ def plot_benchmark_portfolio_returns(
1192
1270
  name=f"{portfolio_name} Positive Returns",
1193
1271
  marker_color=portfolio_color,
1194
1272
  ),
1195
- row=2, col=1
1273
+ row=2,
1274
+ col=1,
1196
1275
  )
1197
-
1276
+
1198
1277
  # Add negative portfolio returns bar chart with darker color
1199
1278
  if not negative_portfolio.empty:
1200
1279
  fig.add_trace(
@@ -1204,40 +1283,41 @@ def plot_benchmark_portfolio_returns(
1204
1283
  name=f"{portfolio_name} Negative Returns",
1205
1284
  marker_color=portfolio_negative_color,
1206
1285
  ),
1207
- row=2, col=1
1286
+ row=2,
1287
+ col=1,
1208
1288
  )
1209
-
1289
+
1210
1290
  # Update layout
1211
1291
  if plot_title is not None:
1212
1292
  title_text = f"{plot_title} ({title_suffix} {benchmark_name} Months)"
1213
1293
  else:
1214
1294
  title_text = None
1215
-
1295
+
1216
1296
  fig.update_layout(
1217
1297
  title_text=title_text,
1218
1298
  showlegend=False,
1219
1299
  height=800,
1220
1300
  margin=dict(l=50, r=50, t=50, b=50), # Standard margins
1221
1301
  )
1222
-
1302
+
1223
1303
  # Update x-axis label
1224
1304
  fig.update_xaxes(title_text="Month", row=2, col=1)
1225
-
1305
+
1226
1306
  # Add y-axis labels with custom colors
1227
1307
  fig.update_yaxes(
1228
- title_text=f"{benchmark_name} Return (%)",
1229
- row=1,
1308
+ title_text=f"{benchmark_name} Return (%)",
1309
+ row=1,
1230
1310
  col=1,
1231
1311
  title_font=dict(color=benchmark_color),
1232
- title_standoff=15
1312
+ title_standoff=15,
1233
1313
  )
1234
-
1314
+
1235
1315
  fig.update_yaxes(
1236
- title_text=f"{portfolio_name} Return (%)",
1237
- row=2,
1316
+ title_text=f"{portfolio_name} Return (%)",
1317
+ row=2,
1238
1318
  col=1,
1239
1319
  title_font=dict(color=portfolio_color),
1240
- title_standoff=15
1320
+ title_standoff=15,
1241
1321
  )
1242
-
1322
+
1243
1323
  return fig
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aplotly
3
- Version: 1.1.23
3
+ Version: 1.1.25
4
4
  License: MIT License
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -4,11 +4,12 @@ import pandas as pd
4
4
  from aplotly.plots import plot_multiple_lines
5
5
 
6
6
  fig = plot_multiple_lines(
7
- [pd.Series(np.random.rand(100), index=np.arange(100)) for _ in range(3)],
8
- labels=["Test 1", "Test 2", "Test 3"],
9
- styles=[{"shape": "hv"}, {"shape": "vh"}, {"shape": "linear"}],
7
+ [pd.Series(np.random.rand(100), index=np.arange(100)) for _ in range(8)],
8
+ labels=["Test 1", "Test 2", "Test 3", "Test 4", "Test 5", "Test 6", "Test 7", "Test 8"],
9
+ styles=[{"shape": "hv"}, {"shape": "vh"}, {"shape": "linear"}, {"shape": "hv"}, {"shape": "vh"}, {"shape": "linear"}, {"shape": "hv"}, {"shape": "vh"}],
10
10
  xlabel="X",
11
11
  ylabel="Y",
12
- colors=["rgba(255, 0, 0, 1.0)", "rgba(0, 255, 0, 0.5)", "rgba(0, 0, 255, 0.25)"],
12
+ color_palette="contrast",
13
+ fade_secondary_lines=True,
13
14
  )
14
15
  fig.show()
@@ -8,5 +8,6 @@ fig = plot_multiple_performance(
8
8
  [pd.Series(np.random.rand(100), index=np.arange(100)) for _ in range(3)],
9
9
  labels=["Test 1", "Test 2", "Test 3"],
10
10
  xlabel="X",
11
+ color_palette="contrast",
11
12
  )
12
13
  fig.show()
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aplotly"
7
- version = "1.1.23"
7
+ version = "1.1.25"
8
8
  readme = "README.md"
9
9
  license = { file = "LICENSE" }
10
10
  classifiers = [
@@ -19,7 +19,7 @@ dependencies = [
19
19
  requires-python = ">=3.10"
20
20
 
21
21
  [tool.bumpver]
22
- current_version = "1.1.23"
22
+ current_version = "1.1.25"
23
23
  version_pattern = "MAJOR.MINOR.PATCH"
24
24
  commit_message = "Bump version {old_version} -> {new_version}"
25
25
  commit = true
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes