openseries 2.1.1__tar.gz → 2.1.2__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.
- {openseries-2.1.1 → openseries-2.1.2}/PKG-INFO +1 -1
- {openseries-2.1.1 → openseries-2.1.2}/openseries/report.py +361 -140
- {openseries-2.1.1 → openseries-2.1.2}/pyproject.toml +5 -6
- {openseries-2.1.1 → openseries-2.1.2}/LICENSE.md +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/README.md +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/__init__.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/_common_model.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/_risk.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/datefixer.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/frame.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/load_plotly.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/owntypes.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/plotly_captor_logo.json +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/plotly_layouts.json +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/portfoliotools.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/py.typed +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/series.py +0 -0
- {openseries-2.1.1 → openseries-2.1.2}/openseries/simulation.py +0 -0
|
@@ -424,9 +424,6 @@ def _configure_figure_layout(
|
|
|
424
424
|
add_logo: bool,
|
|
425
425
|
vertical_legend: bool,
|
|
426
426
|
title: str | None,
|
|
427
|
-
mobile: bool = False,
|
|
428
|
-
total_min_height: int | None = None,
|
|
429
|
-
table_min_height: int | None = None,
|
|
430
427
|
) -> None:
|
|
431
428
|
"""Configure figure layout with logo, legend, and title.
|
|
432
429
|
|
|
@@ -436,14 +433,12 @@ def _configure_figure_layout(
|
|
|
436
433
|
add_logo: Whether to add logo.
|
|
437
434
|
vertical_legend: Whether to use vertical legend.
|
|
438
435
|
title: Optional title for the figure.
|
|
439
|
-
mobile: Whether this is a mobile layout. Defaults to False.
|
|
440
|
-
total_min_height: Minimum total height for mobile layout in pixels.
|
|
441
|
-
table_min_height: Minimum height for table subplot in pixels.
|
|
442
436
|
"""
|
|
443
437
|
fig, logo = load_plotly_dict()
|
|
444
438
|
|
|
445
439
|
if add_logo:
|
|
446
|
-
|
|
440
|
+
logo_copy = logo.copy()
|
|
441
|
+
figure.add_layout_image(logo_copy)
|
|
447
442
|
|
|
448
443
|
figure.update_layout(fig.get("layout"))
|
|
449
444
|
colorway: list[str] = cast("dict[str, list[str]]", fig["layout"]).get(
|
|
@@ -468,24 +463,6 @@ def _configure_figure_layout(
|
|
|
468
463
|
"orientation": "h",
|
|
469
464
|
}
|
|
470
465
|
|
|
471
|
-
if mobile:
|
|
472
|
-
if vertical_legend:
|
|
473
|
-
legend = {
|
|
474
|
-
"yanchor": "top",
|
|
475
|
-
"y": 1.02,
|
|
476
|
-
"xanchor": "left",
|
|
477
|
-
"x": 0,
|
|
478
|
-
"orientation": "h",
|
|
479
|
-
}
|
|
480
|
-
else:
|
|
481
|
-
legend = {
|
|
482
|
-
"yanchor": "top",
|
|
483
|
-
"y": 1.02,
|
|
484
|
-
"xanchor": "left",
|
|
485
|
-
"x": 0,
|
|
486
|
-
"orientation": "h",
|
|
487
|
-
}
|
|
488
|
-
|
|
489
466
|
layout_updates: dict[str, object] = {
|
|
490
467
|
"legend": legend,
|
|
491
468
|
"colorway": colorway[: copied.item_count],
|
|
@@ -493,59 +470,11 @@ def _configure_figure_layout(
|
|
|
493
470
|
"margin": {"l": 50, "r": 50, "t": 80, "b": 50, "pad": 10},
|
|
494
471
|
}
|
|
495
472
|
|
|
496
|
-
if mobile and total_min_height is not None:
|
|
497
|
-
layout_updates["height"] = total_min_height
|
|
498
|
-
layout_updates["autosize"] = False
|
|
499
|
-
|
|
500
473
|
figure.update_layout(**layout_updates)
|
|
501
474
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
automargin=True,
|
|
506
|
-
tickangle=-45,
|
|
507
|
-
row=1,
|
|
508
|
-
col=1,
|
|
509
|
-
)
|
|
510
|
-
figure.update_xaxes(
|
|
511
|
-
gridcolor="#EEEEEE",
|
|
512
|
-
automargin=True,
|
|
513
|
-
tickangle=-45,
|
|
514
|
-
row=2,
|
|
515
|
-
col=1,
|
|
516
|
-
)
|
|
517
|
-
figure.update_yaxes(
|
|
518
|
-
tickformat=".2%",
|
|
519
|
-
gridcolor="#EEEEEE",
|
|
520
|
-
automargin=True,
|
|
521
|
-
row=1,
|
|
522
|
-
col=1,
|
|
523
|
-
)
|
|
524
|
-
figure.update_yaxes(
|
|
525
|
-
tickformat=".2%",
|
|
526
|
-
gridcolor="#EEEEEE",
|
|
527
|
-
automargin=True,
|
|
528
|
-
row=2,
|
|
529
|
-
col=1,
|
|
530
|
-
)
|
|
531
|
-
if table_min_height is not None and total_min_height is not None:
|
|
532
|
-
plot_height = 400
|
|
533
|
-
bar_height = 350
|
|
534
|
-
spacing = 0.08
|
|
535
|
-
plot_domain_top = 1.0
|
|
536
|
-
plot_domain_bottom = 1.0 - (plot_height / total_min_height)
|
|
537
|
-
bar_domain_top = plot_domain_bottom - spacing
|
|
538
|
-
bar_domain_bottom = bar_domain_top - (bar_height / total_min_height)
|
|
539
|
-
|
|
540
|
-
figure.update_layout(
|
|
541
|
-
yaxis_domain=[plot_domain_bottom, plot_domain_top],
|
|
542
|
-
yaxis2_domain=[bar_domain_bottom, bar_domain_top],
|
|
543
|
-
)
|
|
544
|
-
title_size = 24
|
|
545
|
-
else:
|
|
546
|
-
figure.update_xaxes(gridcolor="#EEEEEE", automargin=True, tickangle=-45)
|
|
547
|
-
figure.update_yaxes(tickformat=".2%", gridcolor="#EEEEEE", automargin=True)
|
|
548
|
-
title_size = 36
|
|
475
|
+
figure.update_xaxes(gridcolor="#EEEEEE", automargin=True, tickangle=-45)
|
|
476
|
+
figure.update_yaxes(tickformat=".2%", gridcolor="#EEEEEE", automargin=True)
|
|
477
|
+
title_size = 36
|
|
549
478
|
|
|
550
479
|
if title:
|
|
551
480
|
figure.update_layout(
|
|
@@ -713,16 +642,95 @@ def _build_mobile_figure(
|
|
|
713
642
|
col=1,
|
|
714
643
|
)
|
|
715
644
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
645
|
+
fig, logo = load_plotly_dict()
|
|
646
|
+
|
|
647
|
+
if add_logo:
|
|
648
|
+
logo_copy = logo.copy()
|
|
649
|
+
logo_copy["x"] = 0.99
|
|
650
|
+
logo_copy["xanchor"] = "right"
|
|
651
|
+
figure_mobile.add_layout_image(logo_copy)
|
|
652
|
+
|
|
653
|
+
figure_mobile.update_layout(fig.get("layout"))
|
|
654
|
+
colorway: list[str] = cast("dict[str, list[str]]", fig["layout"]).get(
|
|
655
|
+
"colorway",
|
|
656
|
+
[],
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
if vertical_legend:
|
|
660
|
+
legend = {
|
|
661
|
+
"yanchor": "bottom",
|
|
662
|
+
"y": -0.04,
|
|
663
|
+
"xanchor": "right",
|
|
664
|
+
"x": 0.98,
|
|
665
|
+
"orientation": "v",
|
|
666
|
+
}
|
|
667
|
+
else:
|
|
668
|
+
legend = {
|
|
669
|
+
"yanchor": "bottom",
|
|
670
|
+
"y": -0.2,
|
|
671
|
+
"xanchor": "right",
|
|
672
|
+
"x": 0.98,
|
|
673
|
+
"orientation": "h",
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
layout_updates: dict[str, object] = {
|
|
677
|
+
"legend": legend,
|
|
678
|
+
"colorway": colorway[: copied.item_count],
|
|
679
|
+
"autosize": False,
|
|
680
|
+
"height": total_min_height,
|
|
681
|
+
"margin": {"l": 50, "r": 50, "t": 80, "b": 50, "pad": 10},
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
figure_mobile.update_layout(**layout_updates)
|
|
685
|
+
|
|
686
|
+
figure_mobile.update_xaxes(
|
|
687
|
+
gridcolor="#EEEEEE",
|
|
688
|
+
automargin=True,
|
|
689
|
+
tickangle=-45,
|
|
690
|
+
row=1,
|
|
691
|
+
col=1,
|
|
692
|
+
)
|
|
693
|
+
figure_mobile.update_xaxes(
|
|
694
|
+
gridcolor="#EEEEEE",
|
|
695
|
+
automargin=True,
|
|
696
|
+
tickangle=-45,
|
|
697
|
+
row=2,
|
|
698
|
+
col=1,
|
|
699
|
+
)
|
|
700
|
+
figure_mobile.update_yaxes(
|
|
701
|
+
tickformat=".2%",
|
|
702
|
+
gridcolor="#EEEEEE",
|
|
703
|
+
automargin=True,
|
|
704
|
+
row=1,
|
|
705
|
+
col=1,
|
|
706
|
+
)
|
|
707
|
+
figure_mobile.update_yaxes(
|
|
708
|
+
tickformat=".2%",
|
|
709
|
+
gridcolor="#EEEEEE",
|
|
710
|
+
automargin=True,
|
|
711
|
+
row=2,
|
|
712
|
+
col=1,
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
plot_height = 400
|
|
716
|
+
bar_height = 350
|
|
717
|
+
spacing = 0.08
|
|
718
|
+
plot_domain_top = 1.0
|
|
719
|
+
plot_domain_bottom = 1.0 - (plot_height / total_min_height)
|
|
720
|
+
bar_domain_top = plot_domain_bottom - spacing
|
|
721
|
+
bar_domain_bottom = bar_domain_top - (bar_height / total_min_height)
|
|
722
|
+
|
|
723
|
+
figure_mobile.update_layout(
|
|
724
|
+
yaxis_domain=[plot_domain_bottom, plot_domain_top],
|
|
725
|
+
yaxis2_domain=[bar_domain_bottom, bar_domain_top],
|
|
724
726
|
)
|
|
725
727
|
|
|
728
|
+
title_size = 24
|
|
729
|
+
if title:
|
|
730
|
+
figure_mobile.update_layout(
|
|
731
|
+
{"title": {"text": f"<b>{title}</b><br>", "font": {"size": title_size}}},
|
|
732
|
+
)
|
|
733
|
+
|
|
726
734
|
return figure_mobile
|
|
727
735
|
|
|
728
736
|
|
|
@@ -830,7 +838,10 @@ def _generate_responsive_html_string(
|
|
|
830
838
|
"""
|
|
831
839
|
desktop_style = "width:100%;"
|
|
832
840
|
mobile_style = "width:100%; display:none;"
|
|
833
|
-
match_media =
|
|
841
|
+
match_media = (
|
|
842
|
+
'(window.matchMedia("(max-width: 960px)").matches || '
|
|
843
|
+
'"ontouchstart" in window || navigator.maxTouchPoints > 0)'
|
|
844
|
+
)
|
|
834
845
|
desktop_get = f'document.getElementById("{div_id_desktop}_container")'
|
|
835
846
|
mobile_get = f'document.getElementById("{div_id_mobile}_container")'
|
|
836
847
|
|
|
@@ -847,7 +858,7 @@ def _generate_responsive_html_string(
|
|
|
847
858
|
f"</div>\n"
|
|
848
859
|
"<style>\n"
|
|
849
860
|
"body { overflow-y: auto; }\n"
|
|
850
|
-
"@media (max-width: 960px) {\n"
|
|
861
|
+
"@media (max-width: 960px), (pointer: coarse), (hover: none) {\n"
|
|
851
862
|
" .plotly-desktop { display: none !important; }\n"
|
|
852
863
|
" .plotly-mobile { display: block !important; "
|
|
853
864
|
"overflow: visible !important; }\n"
|
|
@@ -871,13 +882,55 @@ def _generate_responsive_html_string(
|
|
|
871
882
|
" .plotly-mobile [style*='overflow'] { "
|
|
872
883
|
"overflow: visible !important; overflow-y: visible !important; }\n"
|
|
873
884
|
"}\n"
|
|
874
|
-
"@media (min-width: 961px) {\n"
|
|
885
|
+
"@media (min-width: 961px) and (pointer: fine) and (hover: hover) {\n"
|
|
875
886
|
" .plotly-desktop { display: block !important; }\n"
|
|
876
887
|
" .plotly-mobile { display: none !important; }\n"
|
|
888
|
+
" .plotly-desktop .js-plotly-plot { "
|
|
889
|
+
"overflow: hidden !important; overflow-y: hidden !important; "
|
|
890
|
+
"overflow-x: hidden !important; }\n"
|
|
891
|
+
" .plotly-desktop .js-plotly-plot > div { "
|
|
892
|
+
"overflow: hidden !important; overflow-y: hidden !important; "
|
|
893
|
+
"overflow-x: hidden !important; max-height: 100% !important; }\n"
|
|
894
|
+
" .plotly-desktop .js-plotly-plot svg { "
|
|
895
|
+
"overflow: hidden !important; }\n"
|
|
896
|
+
" .plotly-desktop * { "
|
|
897
|
+
"overflow-y: hidden !important; }\n"
|
|
898
|
+
' .plotly-desktop [style*="overflow"] { '
|
|
899
|
+
"overflow: hidden !important; overflow-y: hidden !important; }\n"
|
|
900
|
+
" .plotly-desktop .scrollbar-kit { "
|
|
901
|
+
"display: none !important; visibility: hidden !important; "
|
|
902
|
+
"opacity: 0 !important; }\n"
|
|
903
|
+
" .plotly-desktop .scrollbar-slider { "
|
|
904
|
+
"display: none !important; visibility: hidden !important; "
|
|
905
|
+
"opacity: 0 !important; }\n"
|
|
906
|
+
" .plotly-desktop .scrollbar-glyph { "
|
|
907
|
+
"display: none !important; visibility: hidden !important; "
|
|
908
|
+
"opacity: 0 !important; }\n"
|
|
877
909
|
"}\n"
|
|
878
910
|
"</style>\n"
|
|
879
911
|
"<script>\n"
|
|
880
912
|
"(function() {\n"
|
|
913
|
+
" function adjustLogoPosition(container) {\n"
|
|
914
|
+
" if (!container) return;\n"
|
|
915
|
+
" var plots = container.querySelectorAll('.js-plotly-plot');\n"
|
|
916
|
+
" plots.forEach(function(plot) {\n"
|
|
917
|
+
" var svg = plot.querySelector('svg');\n"
|
|
918
|
+
" if (!svg) return;\n"
|
|
919
|
+
" var images = svg.querySelectorAll('image[xref=\"paper\"]');\n"
|
|
920
|
+
" images.forEach(function(img) {\n"
|
|
921
|
+
" var isNarrow = window.matchMedia("
|
|
922
|
+
"'(max-width: 960px)').matches;\n"
|
|
923
|
+
" if (isNarrow) {\n"
|
|
924
|
+
" img.setAttribute('x', '0.99');\n"
|
|
925
|
+
" img.setAttribute('xanchor', 'right');\n"
|
|
926
|
+
" } else {\n"
|
|
927
|
+
" img.setAttribute('x', '0.01');\n"
|
|
928
|
+
" img.removeAttribute('xanchor');\n"
|
|
929
|
+
" }\n"
|
|
930
|
+
" });\n"
|
|
931
|
+
" });\n"
|
|
932
|
+
" }\n"
|
|
933
|
+
"\n"
|
|
881
934
|
" function updateLayout() {\n"
|
|
882
935
|
f" var isMobile = {match_media};\n"
|
|
883
936
|
f" var desktopContainer = {desktop_get};\n"
|
|
@@ -900,12 +953,71 @@ def _generate_responsive_html_string(
|
|
|
900
953
|
'mobileContainer.style.display = "none";\n'
|
|
901
954
|
" disableTableScrolling(desktopContainer);\n"
|
|
902
955
|
" setTimeout(function() { "
|
|
903
|
-
"adjustTableSize(desktopContainer);
|
|
956
|
+
"adjustTableSize(desktopContainer); "
|
|
957
|
+
"adjustLogoPosition(desktopContainer); }, 100);\n"
|
|
904
958
|
" }\n"
|
|
959
|
+
" adjustLogoPosition(desktopContainer);\n"
|
|
905
960
|
" }\n"
|
|
906
961
|
"\n"
|
|
907
962
|
" function adjustTableSize(container) {\n"
|
|
908
963
|
" if (!container) return;\n"
|
|
964
|
+
" \n"
|
|
965
|
+
" function forceNoScroll() {\n"
|
|
966
|
+
" var scrollbarKits = container.querySelectorAll("
|
|
967
|
+
"'.scrollbar-kit');\n"
|
|
968
|
+
" scrollbarKits.forEach(function(el) {\n"
|
|
969
|
+
" el.style.setProperty('display', 'none', "
|
|
970
|
+
"'important');\n"
|
|
971
|
+
" el.style.setProperty('visibility', 'hidden', "
|
|
972
|
+
"'important');\n"
|
|
973
|
+
" el.style.setProperty('opacity', '0', 'important');\n"
|
|
974
|
+
" });\n"
|
|
975
|
+
" \n"
|
|
976
|
+
" var scrollbarSliders = container.querySelectorAll("
|
|
977
|
+
"'.scrollbar-slider');\n"
|
|
978
|
+
" scrollbarSliders.forEach(function(el) {\n"
|
|
979
|
+
" el.style.setProperty('display', 'none', "
|
|
980
|
+
"'important');\n"
|
|
981
|
+
" el.style.setProperty('visibility', 'hidden', "
|
|
982
|
+
"'important');\n"
|
|
983
|
+
" el.style.setProperty('opacity', '0', 'important');\n"
|
|
984
|
+
" });\n"
|
|
985
|
+
" \n"
|
|
986
|
+
" var scrollbarGlyphs = container.querySelectorAll("
|
|
987
|
+
"'.scrollbar-glyph');\n"
|
|
988
|
+
" scrollbarGlyphs.forEach(function(el) {\n"
|
|
989
|
+
" el.style.setProperty('display', 'none', "
|
|
990
|
+
"'important');\n"
|
|
991
|
+
" el.style.setProperty('visibility', 'hidden', "
|
|
992
|
+
"'important');\n"
|
|
993
|
+
" el.style.setProperty('opacity', '0', 'important');\n"
|
|
994
|
+
" });\n"
|
|
995
|
+
" \n"
|
|
996
|
+
" var allElements = container.querySelectorAll('*');\n"
|
|
997
|
+
" allElements.forEach(function(el) {\n"
|
|
998
|
+
" var computed = window.getComputedStyle(el);\n"
|
|
999
|
+
" if (computed.overflowY === 'auto' || "
|
|
1000
|
+
"computed.overflowY === 'scroll' || computed.overflow === 'auto' || "
|
|
1001
|
+
"computed.overflow === 'scroll') {\n"
|
|
1002
|
+
" el.style.setProperty('overflow', 'hidden', "
|
|
1003
|
+
"'important');\n"
|
|
1004
|
+
" el.style.setProperty('overflow-y', 'hidden', "
|
|
1005
|
+
"'important');\n"
|
|
1006
|
+
" el.style.setProperty('overflow-x', 'hidden', "
|
|
1007
|
+
"'important');\n"
|
|
1008
|
+
" }\n"
|
|
1009
|
+
" if (el.scrollHeight > el.clientHeight && "
|
|
1010
|
+
"el.clientHeight > 0) {\n"
|
|
1011
|
+
" el.style.setProperty('max-height', "
|
|
1012
|
+
"el.clientHeight + 'px', 'important');\n"
|
|
1013
|
+
" el.style.setProperty('overflow', 'hidden', "
|
|
1014
|
+
"'important');\n"
|
|
1015
|
+
" el.style.setProperty('overflow-y', 'hidden', "
|
|
1016
|
+
"'important');\n"
|
|
1017
|
+
" }\n"
|
|
1018
|
+
" });\n"
|
|
1019
|
+
" }\n"
|
|
1020
|
+
" \n"
|
|
909
1021
|
" var plots = container.querySelectorAll('.js-plotly-plot');\n"
|
|
910
1022
|
" plots.forEach(function(plot) {\n"
|
|
911
1023
|
" var svg = plot.querySelector('svg');\n"
|
|
@@ -914,89 +1026,197 @@ def _generate_responsive_html_string(
|
|
|
914
1026
|
" if (!tableGroup) return;\n"
|
|
915
1027
|
" var plotRect = plot.getBoundingClientRect();\n"
|
|
916
1028
|
" if (plotRect.height === 0) return;\n"
|
|
917
|
-
"
|
|
1029
|
+
" \n"
|
|
1030
|
+
" function adjustTable() {\n"
|
|
918
1031
|
" try {\n"
|
|
919
|
-
"
|
|
920
|
-
"
|
|
921
|
-
" var availableHeight = plotRect.height -
|
|
922
|
-
"
|
|
923
|
-
"
|
|
924
|
-
"
|
|
925
|
-
"
|
|
926
|
-
"
|
|
927
|
-
"
|
|
928
|
-
"
|
|
929
|
-
"
|
|
930
|
-
"
|
|
931
|
-
"
|
|
1032
|
+
" forceNoScroll();\n"
|
|
1033
|
+
" \n"
|
|
1034
|
+
" var availableHeight = plotRect.height - 100;\n"
|
|
1035
|
+
" if (availableHeight <= 0) return;\n"
|
|
1036
|
+
" \n"
|
|
1037
|
+
" var rows = tableGroup.querySelectorAll("
|
|
1038
|
+
"'g[class*=\"row\"]');\n"
|
|
1039
|
+
" if (rows.length === 0) return;\n"
|
|
1040
|
+
" \n"
|
|
1041
|
+
" var rowCount = rows.length;\n"
|
|
1042
|
+
" var calculatedRowHeight = availableHeight / rowCount;\n"
|
|
1043
|
+
" var minRowHeight = 18;\n"
|
|
1044
|
+
" var maxRowHeight = 35;\n"
|
|
1045
|
+
" var rowHeight = Math.max(minRowHeight, "
|
|
1046
|
+
"Math.min(maxRowHeight, calculatedRowHeight));\n"
|
|
1047
|
+
" \n"
|
|
1048
|
+
" var baseFontSize = 12;\n"
|
|
1049
|
+
" var fontScale = rowHeight / 25;\n"
|
|
1050
|
+
" var fontSize = baseFontSize * fontScale;\n"
|
|
1051
|
+
" var minFontSize = 9;\n"
|
|
1052
|
+
" var maxFontSize = 14;\n"
|
|
1053
|
+
" fontSize = Math.max(minFontSize, "
|
|
1054
|
+
"Math.min(maxFontSize, fontSize));\n"
|
|
1055
|
+
" \n"
|
|
1056
|
+
" rows.forEach(function(row, rowIndex) {\n"
|
|
1057
|
+
" var yPos = rowIndex * rowHeight;\n"
|
|
1058
|
+
" var rects = row.querySelectorAll('rect');\n"
|
|
1059
|
+
" var texts = row.querySelectorAll('text');\n"
|
|
1060
|
+
" \n"
|
|
1061
|
+
" rects.forEach(function(rect) {\n"
|
|
1062
|
+
" var currentHeight = "
|
|
1063
|
+
"parseFloat(rect.getAttribute('height') || '25');\n"
|
|
1064
|
+
" if (currentHeight > 0) {\n"
|
|
1065
|
+
" rect.setAttribute('height', "
|
|
1066
|
+
"rowHeight.toString());\n"
|
|
1067
|
+
" var currentY = "
|
|
1068
|
+
"parseFloat(rect.getAttribute('y') || '0');\n"
|
|
1069
|
+
" var rowBaseY = Math.floor(currentY / "
|
|
1070
|
+
"currentHeight) * rowHeight;\n"
|
|
1071
|
+
" rect.setAttribute('y', "
|
|
1072
|
+
"rowBaseY.toString());\n"
|
|
1073
|
+
" }\n"
|
|
1074
|
+
" });\n"
|
|
1075
|
+
" \n"
|
|
1076
|
+
" texts.forEach(function(text) {\n"
|
|
1077
|
+
" text.setAttribute('font-size', "
|
|
1078
|
+
"fontSize.toString());\n"
|
|
1079
|
+
" });\n"
|
|
1080
|
+
" });\n"
|
|
1081
|
+
" \n"
|
|
1082
|
+
" var existingTransform = "
|
|
932
1083
|
"tableGroup.getAttribute('transform') || '';\n"
|
|
933
|
-
"
|
|
1084
|
+
" var translateMatch = "
|
|
934
1085
|
"existingTransform.match(/translate\\(([^)]+)\\)/);\n"
|
|
935
|
-
"
|
|
1086
|
+
" var translate = translateMatch ? "
|
|
936
1087
|
"translateMatch[0] : 'translate(0,0)';\n"
|
|
937
|
-
"
|
|
938
|
-
"
|
|
939
|
-
"
|
|
940
|
-
"scaleTransform);\n"
|
|
941
|
-
" } else if (currentHeight <= availableHeight) {\n"
|
|
942
|
-
" var existingTransform = "
|
|
943
|
-
"tableGroup.getAttribute('transform') || '';\n"
|
|
944
|
-
" var translateMatch = "
|
|
945
|
-
"existingTransform.match(/translate\\(([^)]+)\\)/);\n"
|
|
946
|
-
" var translate = translateMatch ? "
|
|
947
|
-
"translateMatch[0] : 'translate(0,0)';\n"
|
|
948
|
-
" tableGroup.setAttribute('transform', "
|
|
949
|
-
"translate);\n"
|
|
950
|
-
" }\n"
|
|
1088
|
+
" tableGroup.setAttribute('transform', translate);\n"
|
|
1089
|
+
" \n"
|
|
1090
|
+
" forceNoScroll();\n"
|
|
951
1091
|
" } catch (e) {\n"
|
|
952
1092
|
" console.log('Table adjustment error:', e);\n"
|
|
953
1093
|
" }\n"
|
|
954
|
-
" }
|
|
1094
|
+
" }\n"
|
|
1095
|
+
" \n"
|
|
1096
|
+
" setTimeout(adjustTable, 200);\n"
|
|
1097
|
+
" setTimeout(adjustTable, 600);\n"
|
|
1098
|
+
" setTimeout(adjustTable, 1200);\n"
|
|
1099
|
+
" setTimeout(adjustTable, 2000);\n"
|
|
955
1100
|
" });\n"
|
|
956
1101
|
" }\n"
|
|
957
1102
|
"\n"
|
|
958
1103
|
" function disableTableScrolling(container) {\n"
|
|
959
1104
|
" if (!container) return;\n"
|
|
1105
|
+
" var isDesktop = container.classList && "
|
|
1106
|
+
"container.classList.contains('plotly-desktop');\n"
|
|
1107
|
+
" var overflowValue = isDesktop ? 'hidden' : 'visible';\n"
|
|
960
1108
|
" var plots = container.querySelectorAll('.js-plotly-plot');\n"
|
|
961
1109
|
" plots.forEach(function(plot) {\n"
|
|
962
1110
|
" var allElements = plot.querySelectorAll('*');\n"
|
|
963
1111
|
" allElements.forEach(function(el) {\n"
|
|
964
|
-
"
|
|
965
|
-
"
|
|
966
|
-
"
|
|
967
|
-
"
|
|
1112
|
+
" if (el.tagName === 'DIV' || el.tagName === 'SVG') {\n"
|
|
1113
|
+
" var style = window.getComputedStyle(el);\n"
|
|
1114
|
+
" var overflow = style.overflow;\n"
|
|
1115
|
+
" var overflowY = style.overflowY;\n"
|
|
1116
|
+
" if (overflow === 'auto' || overflow === 'scroll' || "
|
|
968
1117
|
"overflowY === 'auto' || overflowY === 'scroll') {\n"
|
|
969
|
-
"
|
|
970
|
-
"'important');\n"
|
|
971
|
-
"
|
|
972
|
-
"'important');\n"
|
|
973
|
-
"
|
|
974
|
-
"'important');\n"
|
|
1118
|
+
" el.style.setProperty('overflow', "
|
|
1119
|
+
"overflowValue, 'important');\n"
|
|
1120
|
+
" el.style.setProperty('overflow-y', "
|
|
1121
|
+
"overflowValue, 'important');\n"
|
|
1122
|
+
" el.style.setProperty('overflow-x', "
|
|
1123
|
+
"overflowValue, 'important');\n"
|
|
1124
|
+
" }\n"
|
|
975
1125
|
" }\n"
|
|
976
1126
|
" });\n"
|
|
977
|
-
" plot.style.setProperty('overflow',
|
|
978
|
-
"
|
|
1127
|
+
" plot.style.setProperty('overflow', overflowValue, "
|
|
1128
|
+
"'important');\n"
|
|
1129
|
+
" plot.style.setProperty('overflow-y', overflowValue, "
|
|
979
1130
|
"'important');\n"
|
|
980
1131
|
" var plotDivs = plot.querySelectorAll('div');\n"
|
|
981
1132
|
" plotDivs.forEach(function(div) {\n"
|
|
982
|
-
" div.style.setProperty('overflow',
|
|
1133
|
+
" div.style.setProperty('overflow', overflowValue, "
|
|
983
1134
|
"'important');\n"
|
|
984
|
-
" div.style.setProperty('overflow-y',
|
|
1135
|
+
" div.style.setProperty('overflow-y', overflowValue, "
|
|
985
1136
|
"'important');\n"
|
|
986
1137
|
" });\n"
|
|
987
1138
|
" var svgs = plot.querySelectorAll('svg');\n"
|
|
988
1139
|
" svgs.forEach(function(svg) {\n"
|
|
989
|
-
" svg.style.setProperty('overflow',
|
|
1140
|
+
" svg.style.setProperty('overflow', overflowValue, "
|
|
990
1141
|
"'important');\n"
|
|
991
|
-
" svg.setAttribute('overflow',
|
|
1142
|
+
" svg.setAttribute('overflow', overflowValue);\n"
|
|
992
1143
|
" });\n"
|
|
993
1144
|
" });\n"
|
|
994
1145
|
" }\n"
|
|
995
1146
|
"\n"
|
|
996
1147
|
" function setupScrollObserver(container) {\n"
|
|
997
1148
|
" if (!container) return;\n"
|
|
1149
|
+
" var isDesktop = container.classList && "
|
|
1150
|
+
"container.classList.contains('plotly-desktop');\n"
|
|
1151
|
+
" \n"
|
|
1152
|
+
" function preventScrollbars() {\n"
|
|
1153
|
+
" if (isDesktop) {\n"
|
|
1154
|
+
" var scrollbarKits = container.querySelectorAll("
|
|
1155
|
+
"'.scrollbar-kit');\n"
|
|
1156
|
+
" scrollbarKits.forEach(function(el) {\n"
|
|
1157
|
+
" el.style.setProperty('display', 'none', "
|
|
1158
|
+
"'important');\n"
|
|
1159
|
+
" el.style.setProperty('visibility', 'hidden', "
|
|
1160
|
+
"'important');\n"
|
|
1161
|
+
" el.style.setProperty('opacity', '0', 'important');\n"
|
|
1162
|
+
" });\n"
|
|
1163
|
+
" \n"
|
|
1164
|
+
" var scrollbarSliders = container.querySelectorAll("
|
|
1165
|
+
"'.scrollbar-slider');\n"
|
|
1166
|
+
" scrollbarSliders.forEach(function(el) {\n"
|
|
1167
|
+
" el.style.setProperty('display', 'none', "
|
|
1168
|
+
"'important');\n"
|
|
1169
|
+
" el.style.setProperty('visibility', 'hidden', "
|
|
1170
|
+
"'important');\n"
|
|
1171
|
+
" el.style.setProperty('opacity', '0', 'important');\n"
|
|
1172
|
+
" });\n"
|
|
1173
|
+
" \n"
|
|
1174
|
+
" var scrollbarGlyphs = container.querySelectorAll("
|
|
1175
|
+
"'.scrollbar-glyph');\n"
|
|
1176
|
+
" scrollbarGlyphs.forEach(function(el) {\n"
|
|
1177
|
+
" el.style.setProperty('display', 'none', "
|
|
1178
|
+
"'important');\n"
|
|
1179
|
+
" el.style.setProperty('visibility', 'hidden', "
|
|
1180
|
+
"'important');\n"
|
|
1181
|
+
" el.style.setProperty('opacity', '0', 'important');\n"
|
|
1182
|
+
" });\n"
|
|
1183
|
+
" \n"
|
|
1184
|
+
" var plots = container.querySelectorAll('.js-plotly-plot');\n"
|
|
1185
|
+
" plots.forEach(function(plot) {\n"
|
|
1186
|
+
" var allElements = plot.querySelectorAll('*');\n"
|
|
1187
|
+
" allElements.forEach(function(el) {\n"
|
|
1188
|
+
" if (el.tagName === 'DIV' || "
|
|
1189
|
+
"el.tagName === 'SVG') {\n"
|
|
1190
|
+
" var style = window.getComputedStyle(el);\n"
|
|
1191
|
+
" if (style.overflow === 'auto' || "
|
|
1192
|
+
"style.overflow === 'scroll' || style.overflowY === 'auto' || "
|
|
1193
|
+
"style.overflowY === 'scroll') {\n"
|
|
1194
|
+
" el.style.setProperty('overflow', "
|
|
1195
|
+
"'hidden', 'important');\n"
|
|
1196
|
+
" el.style.setProperty('overflow-y', "
|
|
1197
|
+
"'hidden', 'important');\n"
|
|
1198
|
+
" el.style.setProperty('overflow-x', "
|
|
1199
|
+
"'hidden', 'important');\n"
|
|
1200
|
+
" }\n"
|
|
1201
|
+
" }\n"
|
|
1202
|
+
" });\n"
|
|
1203
|
+
" plot.style.setProperty('overflow', 'hidden', "
|
|
1204
|
+
"'important');\n"
|
|
1205
|
+
" var svg = plot.querySelector('svg');\n"
|
|
1206
|
+
" if (svg) {\n"
|
|
1207
|
+
" svg.style.setProperty('overflow', 'hidden', "
|
|
1208
|
+
"'important');\n"
|
|
1209
|
+
" svg.setAttribute('overflow', 'hidden');\n"
|
|
1210
|
+
" }\n"
|
|
1211
|
+
" });\n"
|
|
1212
|
+
" adjustTableSize(container);\n"
|
|
1213
|
+
" } else {\n"
|
|
1214
|
+
" disableTableScrolling(container);\n"
|
|
1215
|
+
" }\n"
|
|
1216
|
+
" }\n"
|
|
1217
|
+
" \n"
|
|
998
1218
|
" var observer = new MutationObserver(function(mutations) {\n"
|
|
999
|
-
"
|
|
1219
|
+
" preventScrollbars();\n"
|
|
1000
1220
|
" });\n"
|
|
1001
1221
|
" observer.observe(container, {\n"
|
|
1002
1222
|
" childList: true,\n"
|
|
@@ -1004,6 +1224,7 @@ def _generate_responsive_html_string(
|
|
|
1004
1224
|
" attributes: true,\n"
|
|
1005
1225
|
" attributeFilter: ['style', 'class']\n"
|
|
1006
1226
|
" });\n"
|
|
1227
|
+
" preventScrollbars();\n"
|
|
1007
1228
|
" return observer;\n"
|
|
1008
1229
|
" }\n"
|
|
1009
1230
|
"\n"
|
|
@@ -1014,6 +1235,7 @@ def _generate_responsive_html_string(
|
|
|
1014
1235
|
" if (desktopContainer && "
|
|
1015
1236
|
'desktopContainer.style.display !== "none") {\n'
|
|
1016
1237
|
" adjustTableSize(desktopContainer);\n"
|
|
1238
|
+
" adjustLogoPosition(desktopContainer);\n"
|
|
1017
1239
|
" }\n"
|
|
1018
1240
|
" }, 100);\n"
|
|
1019
1241
|
" });\n"
|
|
@@ -1031,8 +1253,8 @@ def _generate_responsive_html_string(
|
|
|
1031
1253
|
" }\n"
|
|
1032
1254
|
" if (desktopContainer && "
|
|
1033
1255
|
'desktopContainer.style.display !== "none") {\n'
|
|
1034
|
-
" disableTableScrolling(desktopContainer);\n"
|
|
1035
1256
|
" adjustTableSize(desktopContainer);\n"
|
|
1257
|
+
" adjustLogoPosition(desktopContainer);\n"
|
|
1036
1258
|
" if (!desktopContainer._scrollObserver) {\n"
|
|
1037
1259
|
" desktopContainer._scrollObserver = "
|
|
1038
1260
|
"setupScrollObserver(desktopContainer);\n"
|
|
@@ -1139,12 +1361,11 @@ def report_html(
|
|
|
1139
1361
|
plotfile = dirpath / filename
|
|
1140
1362
|
|
|
1141
1363
|
_configure_figure_layout(
|
|
1142
|
-
figure,
|
|
1143
|
-
copied,
|
|
1364
|
+
figure=figure,
|
|
1365
|
+
copied=copied,
|
|
1144
1366
|
add_logo=add_logo,
|
|
1145
1367
|
vertical_legend=vertical_legend,
|
|
1146
1368
|
title=title,
|
|
1147
|
-
mobile=False,
|
|
1148
1369
|
)
|
|
1149
1370
|
|
|
1150
1371
|
figure_mobile = _build_mobile_figure(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "openseries"
|
|
3
|
-
version = "2.1.
|
|
3
|
+
version = "2.1.2"
|
|
4
4
|
description = "Tools for analyzing financial timeseries."
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Martin Karrin", email = "martin.karrin@captor.se" },
|
|
@@ -67,18 +67,17 @@ pre-commit = ">=4.5.0"
|
|
|
67
67
|
pytest = ">=9.0.2"
|
|
68
68
|
pytest-cov = ">=7.0.0"
|
|
69
69
|
pytest-xdist = ">=3.8.0"
|
|
70
|
-
ruff = "0.14.
|
|
70
|
+
ruff = "0.14.9"
|
|
71
71
|
types-openpyxl = ">=3.1.2"
|
|
72
72
|
scipy-stubs = ">=1.14.1.0"
|
|
73
73
|
types-python-dateutil = ">=2.8.2"
|
|
74
74
|
types-requests = ">=2.20.0"
|
|
75
75
|
|
|
76
76
|
[tool.poetry.group.docs.dependencies]
|
|
77
|
-
|
|
78
|
-
sphinx = ">=8.2.3"
|
|
77
|
+
sphinx = ">=9.0.4"
|
|
79
78
|
sphinx-autobuild = ">=2025.8.25"
|
|
80
|
-
sphinx-autodoc-typehints = ">=3.
|
|
81
|
-
sphinx-rtd-theme = ">=3.
|
|
79
|
+
sphinx-autodoc-typehints = ">=3.6.0"
|
|
80
|
+
sphinx-rtd-theme = ">=3.1.0rc1"
|
|
82
81
|
|
|
83
82
|
[build-system]
|
|
84
83
|
requires = ["poetry-core>=2.2.1"]
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|