auto-chart-patterns 0.1.0__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.
- auto_chart_patterns-0.1.0/.gitignore +36 -0
- auto_chart_patterns-0.1.0/LICENSE +21 -0
- auto_chart_patterns-0.1.0/Makefile +17 -0
- auto_chart_patterns-0.1.0/PKG-INFO +17 -0
- auto_chart_patterns-0.1.0/README.md +2 -0
- auto_chart_patterns-0.1.0/misc/build_test_cases.ipynb +130 -0
- auto_chart_patterns-0.1.0/misc/test-patterns.ipynb +166 -0
- auto_chart_patterns-0.1.0/pyproject.toml +43 -0
- auto_chart_patterns-0.1.0/src/auto_chart_patterns/__init__.py +0 -0
- auto_chart_patterns-0.1.0/src/auto_chart_patterns/chart_pattern.py +169 -0
- auto_chart_patterns-0.1.0/src/auto_chart_patterns/line.py +84 -0
- auto_chart_patterns-0.1.0/src/auto_chart_patterns/reversal_patterns.py +202 -0
- auto_chart_patterns-0.1.0/src/auto_chart_patterns/rsi_div_patterns.py +146 -0
- auto_chart_patterns-0.1.0/src/auto_chart_patterns/trendline_patterns.py +446 -0
- auto_chart_patterns-0.1.0/src/auto_chart_patterns/zigzag.py +228 -0
- auto_chart_patterns-0.1.0/tests/__init__.py +0 -0
- auto_chart_patterns-0.1.0/tests/integration/__init__.py +0 -0
- auto_chart_patterns-0.1.0/tests/integration/conftest.py +31 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-02.csv +168 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-11.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2023-12.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-02.csv +174 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/AVAXUSDT/AVAXUSDT-4h-2024-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-02.csv +168 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-11.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2023-12.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-02.csv +174 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/BTCUSDT/BTCUSDT-4h-2024-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-02.csv +168 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-11.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2023-12.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-02.csv +174 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/DOGEUSDT/DOGEUSDT-4h-2024-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-02.csv +168 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-11.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2023-12.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-02.csv +174 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/ETHUSDT/ETHUSDT-4h-2024-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-02.csv +168 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-11.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2023-12.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-02.csv +174 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-07.csv +42 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SHIBUSDT/SHIBUSDT-4h-2024-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-02.csv +168 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-11.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2023-12.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-01.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-02.csv +174 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-03.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-04.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-05.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-06.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-07.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-08.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-09.csv +180 -0
- auto_chart_patterns-0.1.0/tests/integration/data/SOLUSDT/SOLUSDT-4h-2024-10.csv +186 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/AVAXUSDT_flags_pennants_patterns.json +232 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/AVAXUSDT_flags_pennants_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/BTCUSDT_flags_pennants_patterns.json +94 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/BTCUSDT_flags_pennants_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/DOGEUSDT_flags_pennants_patterns.json +48 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/DOGEUSDT_flags_pennants_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/ETHUSDT_flags_pennants_patterns.json +278 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/ETHUSDT_flags_pennants_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/SHIBUSDT_flags_pennants_patterns.json +186 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/SHIBUSDT_flags_pennants_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/SOLUSDT_flags_pennants_patterns.json +324 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/flags_pennants/SOLUSDT_flags_pennants_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/AVAXUSDT_reversals_patterns.json +302 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/AVAXUSDT_reversals_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/BTCUSDT_reversals_patterns.json +474 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/BTCUSDT_reversals_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/DOGEUSDT_reversals_patterns.json +378 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/DOGEUSDT_reversals_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/ETHUSDT_reversals_patterns.json +302 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/ETHUSDT_reversals_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/SHIBUSDT_reversals_patterns.json +190 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/SHIBUSDT_reversals_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/SOLUSDT_reversals_patterns.json +266 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/reversals/SOLUSDT_reversals_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/AVAXUSDT_trend_lines_patterns.json +450 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/AVAXUSDT_trend_lines_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/BTCUSDT_trend_lines_patterns.json +226 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/BTCUSDT_trend_lines_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/DOGEUSDT_trend_lines_patterns.json +170 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/DOGEUSDT_trend_lines_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/ETHUSDT_trend_lines_patterns.json +338 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/ETHUSDT_trend_lines_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/SHIBUSDT_trend_lines_patterns.json +282 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/SHIBUSDT_trend_lines_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/SOLUSDT_trend_lines_patterns.json +338 -0
- auto_chart_patterns-0.1.0/tests/integration/fixtures/trend_lines/SOLUSDT_trend_lines_patterns.png +0 -0
- auto_chart_patterns-0.1.0/tests/integration/helpers.py +165 -0
- auto_chart_patterns-0.1.0/tests/integration/test_flags_pennants.py +57 -0
- auto_chart_patterns-0.1.0/tests/integration/test_reversals.py +54 -0
- auto_chart_patterns-0.1.0/tests/integration/test_trend_lines.py +56 -0
- auto_chart_patterns-0.1.0/tests/test_reversal_patterns.py +106 -0
- auto_chart_patterns-0.1.0/tests/test_rsi_divergence.py +133 -0
- auto_chart_patterns-0.1.0/tests/test_trend_lines.py +96 -0
- auto_chart_patterns-0.1.0/tests/test_zigzag.py +42 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Hatch
|
|
2
|
+
.hatch/
|
|
3
|
+
.venv/
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*$py.class
|
|
9
|
+
*.so
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# IDE
|
|
28
|
+
.idea/
|
|
29
|
+
.vscode/
|
|
30
|
+
*.swp
|
|
31
|
+
*.swo
|
|
32
|
+
|
|
33
|
+
# Environment
|
|
34
|
+
.env
|
|
35
|
+
env/
|
|
36
|
+
ENV/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 FanM
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.PHONY: build test upload clean
|
|
2
|
+
|
|
3
|
+
build:
|
|
4
|
+
python -m build
|
|
5
|
+
|
|
6
|
+
test:
|
|
7
|
+
hatch env run test
|
|
8
|
+
|
|
9
|
+
upload:
|
|
10
|
+
python -m twine upload dist/*
|
|
11
|
+
|
|
12
|
+
clean:
|
|
13
|
+
rm -rf dist/ build/ *.egg-info/
|
|
14
|
+
|
|
15
|
+
# Upload to test PyPI
|
|
16
|
+
upload-test:
|
|
17
|
+
python -m twine upload --repository testpypi dist/*
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: auto-chart-patterns
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Automatically identify chart patterns from OHLC data
|
|
5
|
+
Project-URL: Homepage, https://github.com/FanM/auto-chart-patterns
|
|
6
|
+
Project-URL: Bug Tracker, https://github.com/FanM/auto-chart-patterns/issues
|
|
7
|
+
Author-email: Fan Mao <maofan@xsmail.com>
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Requires-Dist: numpy>=1.19.0
|
|
13
|
+
Requires-Dist: pandas>=1.0.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# auto-chart-patterns
|
|
17
|
+
Automatically identify chart patterns from OHLC data
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "code",
|
|
5
|
+
"execution_count": 9,
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"outputs": [],
|
|
8
|
+
"source": [
|
|
9
|
+
"import sys\n",
|
|
10
|
+
"from pathlib import Path\n",
|
|
11
|
+
"\n",
|
|
12
|
+
"# Add project root to Python path\n",
|
|
13
|
+
"project_root = str(Path.cwd().parent) # Assumes notebook is in integration/ directory\n",
|
|
14
|
+
"if project_root not in sys.path:\n",
|
|
15
|
+
" sys.path.append(project_root)\n",
|
|
16
|
+
"\n",
|
|
17
|
+
"import json\n",
|
|
18
|
+
"from typing import List\n",
|
|
19
|
+
"from src.auto_chart_patterns.chart_pattern import ChartPattern\n",
|
|
20
|
+
"from src.auto_chart_patterns.trendline_patterns import find_trend_lines\n",
|
|
21
|
+
"from src.auto_chart_patterns.reversal_patterns import find_reversal_patterns\n",
|
|
22
|
+
"from tests.integration.helpers import get_data_for_ticker, PATTERN_CATEGORIES, START_DATE, END_DATE\n",
|
|
23
|
+
"\n",
|
|
24
|
+
"ticker_list = [\"BTCUSDT\", \"SOLUSDT\", \"ETHUSDT\", \"AVAXUSDT\", \"DOGEUSDT\", \"SHIBUSDT\"]\n",
|
|
25
|
+
"def build_test_cases(ticker: str, category: int, find_patterns_func, zigzag, default_properties):\n",
|
|
26
|
+
" prices = get_data_for_ticker(ticker, start_date=START_DATE,\n",
|
|
27
|
+
" end_date=END_DATE)\n",
|
|
28
|
+
" zigzag.calculate(prices)\n",
|
|
29
|
+
"\n",
|
|
30
|
+
" patterns: List[ChartPattern] = []\n",
|
|
31
|
+
" for i in range(0, len(zigzag.zigzag_pivots)):\n",
|
|
32
|
+
" find_patterns_func(zigzag, i, default_properties, patterns)\n",
|
|
33
|
+
"\n",
|
|
34
|
+
" with open(f'../tests/integration/fixtures/{PATTERN_CATEGORIES[category]}/'\n",
|
|
35
|
+
" f'{ticker}_{PATTERN_CATEGORIES[category]}_patterns.json', 'w') as f:\n",
|
|
36
|
+
" # format json\n",
|
|
37
|
+
" json.dump([pattern.dict() for pattern in patterns], f, indent=4)\n"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"cell_type": "markdown",
|
|
42
|
+
"metadata": {},
|
|
43
|
+
"source": [
|
|
44
|
+
"## Flags & pennants"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"cell_type": "code",
|
|
49
|
+
"execution_count": 6,
|
|
50
|
+
"metadata": {},
|
|
51
|
+
"outputs": [],
|
|
52
|
+
"source": [
|
|
53
|
+
"from tests.integration.helpers import zigzag_fp, scan_properties_fp\n",
|
|
54
|
+
"\n",
|
|
55
|
+
"for ticker in ticker_list:\n",
|
|
56
|
+
" build_test_cases(ticker, 1, find_trend_lines,\n",
|
|
57
|
+
" zigzag_fp, scan_properties_fp)\n"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"cell_type": "markdown",
|
|
62
|
+
"metadata": {},
|
|
63
|
+
"source": [
|
|
64
|
+
"## Trend lines"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"cell_type": "code",
|
|
69
|
+
"execution_count": 2,
|
|
70
|
+
"metadata": {},
|
|
71
|
+
"outputs": [
|
|
72
|
+
{
|
|
73
|
+
"name": "stderr",
|
|
74
|
+
"output_type": "stream",
|
|
75
|
+
"text": [
|
|
76
|
+
"Warning: pivots exceeded limit 50, popping pivot 1\n"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"source": [
|
|
81
|
+
"from tests.integration.helpers import zigzag_tl, scan_properties_tl\n",
|
|
82
|
+
"\n",
|
|
83
|
+
"for ticker in ticker_list:\n",
|
|
84
|
+
" build_test_cases(ticker, 2, find_trend_lines,\n",
|
|
85
|
+
" zigzag_tl, scan_properties_tl)\n"
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"cell_type": "markdown",
|
|
90
|
+
"metadata": {},
|
|
91
|
+
"source": [
|
|
92
|
+
"## Reversal patterns"
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"cell_type": "code",
|
|
97
|
+
"execution_count": 8,
|
|
98
|
+
"metadata": {},
|
|
99
|
+
"outputs": [],
|
|
100
|
+
"source": [
|
|
101
|
+
"from tests.integration.helpers import zigzag_rp, scan_properties_rp\n",
|
|
102
|
+
"\n",
|
|
103
|
+
"for ticker in ticker_list:\n",
|
|
104
|
+
" build_test_cases(ticker, 3, find_reversal_patterns,\n",
|
|
105
|
+
" zigzag_rp, scan_properties_rp)\n"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"metadata": {
|
|
110
|
+
"kernelspec": {
|
|
111
|
+
"display_name": ".venv",
|
|
112
|
+
"language": "python",
|
|
113
|
+
"name": "python3"
|
|
114
|
+
},
|
|
115
|
+
"language_info": {
|
|
116
|
+
"codemirror_mode": {
|
|
117
|
+
"name": "ipython",
|
|
118
|
+
"version": 3
|
|
119
|
+
},
|
|
120
|
+
"file_extension": ".py",
|
|
121
|
+
"mimetype": "text/x-python",
|
|
122
|
+
"name": "python",
|
|
123
|
+
"nbconvert_exporter": "python",
|
|
124
|
+
"pygments_lexer": "ipython3",
|
|
125
|
+
"version": "3.10.15"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"nbformat": 4,
|
|
129
|
+
"nbformat_minor": 2
|
|
130
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "code",
|
|
5
|
+
"execution_count": null,
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"outputs": [],
|
|
8
|
+
"source": [
|
|
9
|
+
"import logging\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"logging.basicConfig(level=logging.DEBUG)"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"cell_type": "code",
|
|
16
|
+
"execution_count": 2,
|
|
17
|
+
"metadata": {},
|
|
18
|
+
"outputs": [],
|
|
19
|
+
"source": [
|
|
20
|
+
"import sys\n",
|
|
21
|
+
"from pathlib import Path\n",
|
|
22
|
+
"\n",
|
|
23
|
+
"# Add project root to Python path\n",
|
|
24
|
+
"project_root = str(Path.cwd().parent) # Assumes notebook is in integration/ directory\n",
|
|
25
|
+
"if project_root not in sys.path:\n",
|
|
26
|
+
" sys.path.append(project_root)\n",
|
|
27
|
+
"\n",
|
|
28
|
+
"import datetime\n",
|
|
29
|
+
"from tests.integration.helpers import get_data_for_ticker\n",
|
|
30
|
+
"\n",
|
|
31
|
+
"prices = get_data_for_ticker(\"SHIBUSDT\", start_date=datetime.datetime(2024, 1, 1), end_date=datetime.datetime(2024, 11, 25))"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"cell_type": "code",
|
|
36
|
+
"execution_count": 3,
|
|
37
|
+
"metadata": {},
|
|
38
|
+
"outputs": [
|
|
39
|
+
{
|
|
40
|
+
"name": "stdout",
|
|
41
|
+
"output_type": "stream",
|
|
42
|
+
"text": [
|
|
43
|
+
"Pivot: time=2024-10-31 00:00:00, index=280, price=1.771e-05, direction=-1\n",
|
|
44
|
+
"Pivot: time=2024-10-29 00:00:00, index=278, price=1.983e-05, direction=2\n",
|
|
45
|
+
"Pivot: time=2024-10-25 00:00:00, index=274, price=1.583e-05, direction=-2\n",
|
|
46
|
+
"Pivot: time=2024-10-19 00:00:00, index=268, price=1.955e-05, direction=2\n",
|
|
47
|
+
"Pivot: time=2024-10-10 00:00:00, index=259, price=1.605e-05, direction=-1\n",
|
|
48
|
+
"Pivot: time=2024-10-06 00:00:00, index=255, price=1.885e-05, direction=1\n",
|
|
49
|
+
"Pivot: time=2024-10-03 00:00:00, index=252, price=1.548e-05, direction=-1\n",
|
|
50
|
+
"Pivot: time=2024-09-27 00:00:00, index=246, price=2.169e-05, direction=2\n",
|
|
51
|
+
"Pivot: time=2024-09-18 00:00:00, index=237, price=1.296e-05, direction=-1\n",
|
|
52
|
+
"Pivot: time=2024-09-13 00:00:00, index=232, price=1.411e-05, direction=2\n",
|
|
53
|
+
"Pivot: time=2024-09-11 00:00:00, index=230, price=1.293e-05, direction=-1\n",
|
|
54
|
+
"Pivot: time=2024-09-09 00:00:00, index=228, price=1.376e-05, direction=1\n",
|
|
55
|
+
"Pivot: time=2024-09-06 00:00:00, index=225, price=1.231e-05, direction=-2\n",
|
|
56
|
+
"Pivot: time=2024-08-24 00:00:00, index=212, price=1.612e-05, direction=2\n",
|
|
57
|
+
"Pivot: time=2024-08-16 00:00:00, index=204, price=1.289e-05, direction=-1\n",
|
|
58
|
+
"Pivot: time=2024-08-11 00:00:00, index=199, price=1.468e-05, direction=1\n",
|
|
59
|
+
"Pivot: time=2024-08-05 00:00:00, index=193, price=1.078e-05, direction=-2\n",
|
|
60
|
+
"Pivot: time=2024-07-06 00:00:00, index=187, price=1.754e-05, direction=1\n",
|
|
61
|
+
"Pivot: time=2024-07-05 00:00:00, index=186, price=1.266e-05, direction=-2\n",
|
|
62
|
+
"Pivot: time=2024-07-01 00:00:00, index=182, price=1.76e-05, direction=1\n",
|
|
63
|
+
"Pivot: time=2024-06-30 00:00:00, index=181, price=1.662e-05, direction=-1\n",
|
|
64
|
+
"Pivot: time=2024-06-25 00:00:00, index=176, price=1.824e-05, direction=1\n",
|
|
65
|
+
"Pivot: time=2024-06-24 00:00:00, index=175, price=1.632e-05, direction=-2\n",
|
|
66
|
+
"Pivot: time=2024-06-05 00:00:00, index=156, price=2.633e-05, direction=1\n",
|
|
67
|
+
"Pivot: time=2024-06-04 00:00:00, index=155, price=2.282e-05, direction=-2\n",
|
|
68
|
+
"Pivot: time=2024-05-29 00:00:00, index=149, price=2.945e-05, direction=2\n",
|
|
69
|
+
"Pivot: time=2024-05-23 00:00:00, index=143, price=2.339e-05, direction=-2\n",
|
|
70
|
+
"Pivot: time=2024-05-22 00:00:00, index=142, price=2.686e-05, direction=2\n",
|
|
71
|
+
"Pivot: time=2024-05-20 00:00:00, index=140, price=2.351e-05, direction=-1\n",
|
|
72
|
+
"Pivot: time=2024-05-16 00:00:00, index=136, price=2.588e-05, direction=1\n",
|
|
73
|
+
"Pivot: time=2024-05-13 00:00:00, index=133, price=2.156e-05, direction=-1\n",
|
|
74
|
+
"Pivot: time=2024-05-04 00:00:00, index=124, price=2.632e-05, direction=1\n",
|
|
75
|
+
"Pivot: time=2024-05-01 00:00:00, index=121, price=2.057e-05, direction=-1\n",
|
|
76
|
+
"Pivot: time=2024-04-21 00:00:00, index=111, price=2.82e-05, direction=1\n",
|
|
77
|
+
"Pivot: time=2024-04-13 00:00:00, index=103, price=1.83e-05, direction=-2\n",
|
|
78
|
+
"Pivot: time=2024-04-08 00:00:00, index=98, price=2.954e-05, direction=1\n",
|
|
79
|
+
"Pivot: time=2024-04-03 00:00:00, index=93, price=2.55e-05, direction=-1\n",
|
|
80
|
+
"Pivot: time=2024-03-28 00:00:00, index=87, price=3.285e-05, direction=1\n",
|
|
81
|
+
"Pivot: time=2024-03-20 00:00:00, index=79, price=2.366e-05, direction=-2\n",
|
|
82
|
+
"Pivot: time=2024-03-14 00:00:00, index=73, price=3.487e-05, direction=1\n",
|
|
83
|
+
"Pivot: time=2024-03-12 00:00:00, index=71, price=2.999e-05, direction=-1\n",
|
|
84
|
+
"Pivot: time=2024-03-05 00:00:00, index=64, price=4.567e-05, direction=2\n",
|
|
85
|
+
"Pivot: time=2024-02-21 00:00:00, index=51, price=9.3e-06, direction=-2\n",
|
|
86
|
+
"Pivot: time=2024-02-20 00:00:00, index=50, price=9.97e-06, direction=1\n",
|
|
87
|
+
"Pivot: time=2024-02-17 00:00:00, index=47, price=9.41e-06, direction=-1\n",
|
|
88
|
+
"Pivot: time=2024-02-15 00:00:00, index=45, price=1.005e-05, direction=2\n",
|
|
89
|
+
"Pivot: time=2024-02-05 00:00:00, index=35, price=8.78e-06, direction=-2\n",
|
|
90
|
+
"Pivot: time=2024-02-03 00:00:00, index=33, price=9.16e-06, direction=1\n",
|
|
91
|
+
"Pivot: time=2024-02-01 00:00:00, index=31, price=8.79e-06, direction=-1\n",
|
|
92
|
+
"Pivot: time=2024-01-30 00:00:00, index=29, price=9.46e-06, direction=1\n",
|
|
93
|
+
"Pivot: time=2024-01-23 00:00:00, index=22, price=8.43e-06, direction=-2\n",
|
|
94
|
+
"Pivot: time=2024-01-20 00:00:00, index=19, price=9.86e-06, direction=1\n",
|
|
95
|
+
"Pivot: time=2024-01-19 00:00:00, index=18, price=8.79e-06, direction=-1\n",
|
|
96
|
+
"Pivot: time=2024-01-11 00:00:00, index=10, price=1.05e-05, direction=1\n",
|
|
97
|
+
"Pivot: time=2024-01-03 00:00:00, index=2, price=8.27e-06, direction=-1\n",
|
|
98
|
+
"Pivot: time=2024-01-02 00:00:00, index=1, price=1.092e-05, direction=1\n"
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
"source": [
|
|
103
|
+
"from auto_chart_patterns.zigzag import Zigzag\n",
|
|
104
|
+
"\n",
|
|
105
|
+
"zigzag = Zigzag(backcandles=2, forwardcandles=2, pivot_limit=100, offset=0)\n",
|
|
106
|
+
"zigzag.calculate(prices)\n",
|
|
107
|
+
"\n",
|
|
108
|
+
"for pivot in zigzag.zigzag_pivots:\n",
|
|
109
|
+
" print(f\"Pivot: time={pivot.point.time}, index={pivot.point.index}, price={pivot.point.price}, direction={pivot.direction}\")\n"
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"cell_type": "code",
|
|
114
|
+
"execution_count": 7,
|
|
115
|
+
"metadata": {},
|
|
116
|
+
"outputs": [
|
|
117
|
+
{
|
|
118
|
+
"name": "stdout",
|
|
119
|
+
"output_type": "stream",
|
|
120
|
+
"text": [
|
|
121
|
+
"Triple Bottoms: 246 - 278\n",
|
|
122
|
+
"Triple Bottoms: 212 - 246\n",
|
|
123
|
+
"Double Bottoms: 156 - 182\n",
|
|
124
|
+
"Double Tops: 121 - 140\n",
|
|
125
|
+
"Double Bottoms: 45 - 64\n",
|
|
126
|
+
"Double Tops: 35 - 51\n",
|
|
127
|
+
"Double Bottoms: 29 - 45\n",
|
|
128
|
+
"Inverted Head and Shoulders: 10 - 33\n"
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
"source": [
|
|
133
|
+
"from auto_chart_patterns.reversal_patterns import find_reversal_patterns, ReversalPatternProperties\n",
|
|
134
|
+
"\n",
|
|
135
|
+
"scan_props = ReversalPatternProperties(min_periods_lapsed=8, flat_ratio=0.1)\n",
|
|
136
|
+
"patterns = []\n",
|
|
137
|
+
"for i in range(0, len(zigzag.zigzag_pivots)):\n",
|
|
138
|
+
" find_reversal_patterns(zigzag, i, scan_props, patterns)\n",
|
|
139
|
+
"\n",
|
|
140
|
+
"for pattern in patterns:\n",
|
|
141
|
+
" print(f\"{pattern.pattern_name}: {pattern.pivots[0].point.index} - {pattern.pivots[-1].point.index}\")"
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
"metadata": {
|
|
146
|
+
"kernelspec": {
|
|
147
|
+
"display_name": ".venv",
|
|
148
|
+
"language": "python",
|
|
149
|
+
"name": "python3"
|
|
150
|
+
},
|
|
151
|
+
"language_info": {
|
|
152
|
+
"codemirror_mode": {
|
|
153
|
+
"name": "ipython",
|
|
154
|
+
"version": 3
|
|
155
|
+
},
|
|
156
|
+
"file_extension": ".py",
|
|
157
|
+
"mimetype": "text/x-python",
|
|
158
|
+
"name": "python",
|
|
159
|
+
"nbconvert_exporter": "python",
|
|
160
|
+
"pygments_lexer": "ipython3",
|
|
161
|
+
"version": "3.10.15"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"nbformat": 4,
|
|
165
|
+
"nbformat_minor": 2
|
|
166
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "auto-chart-patterns"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="Fan Mao", email="maofan@xsmail.com" },
|
|
10
|
+
]
|
|
11
|
+
description = "Automatically identify chart patterns from OHLC data"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.9"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"pandas>=1.0.0",
|
|
21
|
+
"numpy>=1.19.0",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
"Homepage" = "https://github.com/FanM/auto-chart-patterns"
|
|
26
|
+
"Bug Tracker" = "https://github.com/FanM/auto-chart-patterns/issues"
|
|
27
|
+
|
|
28
|
+
[tool.hatch.build.targets.wheel]
|
|
29
|
+
sources = ["src"] # this is the default
|
|
30
|
+
|
|
31
|
+
[tool.hatch.envs.default]
|
|
32
|
+
type = "virtual"
|
|
33
|
+
path = ".venv"
|
|
34
|
+
dependencies = [
|
|
35
|
+
"pytest>=7.0.0",
|
|
36
|
+
"pytest-cov>=4.0.0",
|
|
37
|
+
"build",
|
|
38
|
+
"twine",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[tool.hatch.envs.default.scripts]
|
|
42
|
+
test = "pytest {args:tests}"
|
|
43
|
+
test-cov = "pytest --cov {args:tests}"
|
|
File without changes
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
from abc import abstractmethod
|
|
4
|
+
from .line import Pivot
|
|
5
|
+
from .zigzag import Zigzag
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class ChartPatternProperties:
|
|
13
|
+
offset: int = 0
|
|
14
|
+
min_periods_lapsed: int = 21
|
|
15
|
+
max_live_patterns: int = 50
|
|
16
|
+
avoid_overlap: bool = True # whether to avoid overlapping patterns
|
|
17
|
+
allowed_patterns: List[bool] = None
|
|
18
|
+
allowed_last_pivot_directions: List[int] = None
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class ChartPattern:
|
|
22
|
+
"""Base class for chart patterns"""
|
|
23
|
+
pivots: List[Pivot]
|
|
24
|
+
pattern_type: int = 0
|
|
25
|
+
pattern_name: str = ""
|
|
26
|
+
extra_props: Dict = None # for adding extra properties, not serialized
|
|
27
|
+
|
|
28
|
+
def dict(self):
|
|
29
|
+
return {
|
|
30
|
+
"pivots": [p.dict() for p in self.pivots],
|
|
31
|
+
"pattern_type": self.pattern_type,
|
|
32
|
+
"pattern_name": self.pattern_name
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def __eq__(self, other: 'ChartPattern') -> bool:
|
|
36
|
+
other_pivot_indexes = [p.point.time for p in other.pivots]
|
|
37
|
+
self_pivot_indexes = [p.point.time for p in self.pivots]
|
|
38
|
+
return self.pattern_type == other.pattern_type and \
|
|
39
|
+
self_pivot_indexes == other_pivot_indexes
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def from_dict(cls, dict: dict):
|
|
43
|
+
self = cls(pivots=[Pivot.from_dict(p) for p in dict["pivots"]],
|
|
44
|
+
pattern_type=dict["pattern_type"],
|
|
45
|
+
pattern_name=dict["pattern_name"])
|
|
46
|
+
return self
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def get_pattern_name_by_id(self, pattern_type: int) -> str:
|
|
50
|
+
"""Get pattern name from pattern type ID
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
pattern_type: Pattern type identifier
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
str: Name of the pattern
|
|
57
|
+
"""
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
def process_pattern(self, properties: ChartPatternProperties,
|
|
61
|
+
patterns: List['ChartPattern']) -> bool:
|
|
62
|
+
"""
|
|
63
|
+
Process a new pattern: validate it, check if it's allowed, and manage pattern list
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
properties: Scan properties
|
|
67
|
+
patterns: List of existing patterns
|
|
68
|
+
max_live_patterns: Maximum number of patterns to keep
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
bool: True if pattern was successfully processed and added
|
|
72
|
+
"""
|
|
73
|
+
# Log warning if invalid pattern type detected
|
|
74
|
+
if self.pattern_type == 0:
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
# Get last direction from the last pivot
|
|
78
|
+
last_dir = self.pivots[-1].direction
|
|
79
|
+
|
|
80
|
+
# Get allowed last pivot direction for this pattern type
|
|
81
|
+
allowed_last_pivot_direction = 0
|
|
82
|
+
if properties.allowed_last_pivot_directions is not None:
|
|
83
|
+
if self.pattern_type < len(properties.allowed_last_pivot_directions):
|
|
84
|
+
allowed_last_pivot_direction = properties.allowed_last_pivot_directions[self.pattern_type]
|
|
85
|
+
|
|
86
|
+
# Check if pattern type is allowed
|
|
87
|
+
pattern_allowed = True
|
|
88
|
+
if properties.allowed_patterns is not None:
|
|
89
|
+
if self.pattern_type > len(properties.allowed_patterns):
|
|
90
|
+
pattern_allowed = False
|
|
91
|
+
else:
|
|
92
|
+
pattern_allowed = (self.pattern_type > 0 and
|
|
93
|
+
properties.allowed_patterns[self.pattern_type-1])
|
|
94
|
+
|
|
95
|
+
# Check if direction is allowed
|
|
96
|
+
direction_allowed = (allowed_last_pivot_direction == 0 or
|
|
97
|
+
allowed_last_pivot_direction == last_dir)
|
|
98
|
+
|
|
99
|
+
if pattern_allowed and direction_allowed:
|
|
100
|
+
# Check for existing pattern with same pivots
|
|
101
|
+
existing_pattern = False
|
|
102
|
+
replacing_patterns = []
|
|
103
|
+
|
|
104
|
+
for idx, existing in enumerate(patterns):
|
|
105
|
+
# Check if pivots match
|
|
106
|
+
existing_indexes = set([p.point.time for p in existing.pivots])
|
|
107
|
+
self_indexes = set([p.point.time for p in self.pivots])
|
|
108
|
+
# check if the indexes of self.pivots are a subset of existing.pivots
|
|
109
|
+
if self_indexes == existing_indexes:
|
|
110
|
+
existing_pattern = True
|
|
111
|
+
break
|
|
112
|
+
elif self_indexes.issubset(existing_indexes) and properties.avoid_overlap:
|
|
113
|
+
existing_pattern = True
|
|
114
|
+
break
|
|
115
|
+
elif existing_indexes.issubset(self_indexes) and properties.avoid_overlap:
|
|
116
|
+
replacing_patterns.append(idx)
|
|
117
|
+
|
|
118
|
+
if not existing_pattern:
|
|
119
|
+
for idx in replacing_patterns:
|
|
120
|
+
patterns.pop(idx)
|
|
121
|
+
|
|
122
|
+
# Set pattern name
|
|
123
|
+
self.pattern_name = self.get_pattern_name_by_id(self.pattern_type)
|
|
124
|
+
|
|
125
|
+
# Add new pattern and manage list size
|
|
126
|
+
patterns.append(self)
|
|
127
|
+
while len(patterns) > properties.max_live_patterns:
|
|
128
|
+
patterns.pop(0)
|
|
129
|
+
|
|
130
|
+
return True
|
|
131
|
+
|
|
132
|
+
return False
|
|
133
|
+
|
|
134
|
+
def get_pivots_from_zigzag(zigzag: Zigzag, pivots: List[Pivot], offset: int, min_pivots: int) -> int:
|
|
135
|
+
for i in range(min_pivots):
|
|
136
|
+
pivot = zigzag.get_pivot(i + offset)
|
|
137
|
+
if pivot is None:
|
|
138
|
+
return i
|
|
139
|
+
pivots.insert(0, pivot.deep_copy())
|
|
140
|
+
return i+1
|
|
141
|
+
|
|
142
|
+
def is_same_height(pivot1: Pivot, pivot2: Pivot, ref_pivots: List[Pivot], flat_ratio: float) -> bool:
|
|
143
|
+
# check if two pivots are approximately flat with a list of reference pivots
|
|
144
|
+
# use the first and last pivots in the list as reference points
|
|
145
|
+
if np.sign(pivot1.direction) != np.sign(pivot2.direction):
|
|
146
|
+
raise ValueError("Pivots must have the same direction")
|
|
147
|
+
|
|
148
|
+
# use the reference pivots to calculate the height ratio
|
|
149
|
+
if pivot1.direction > 0:
|
|
150
|
+
ref_prices = np.min([p.point.price for p in ref_pivots])
|
|
151
|
+
else:
|
|
152
|
+
ref_prices = np.max([p.point.price for p in ref_pivots])
|
|
153
|
+
|
|
154
|
+
diff1 = pivot1.point.price - ref_prices
|
|
155
|
+
diff2 = pivot2.point.price - ref_prices
|
|
156
|
+
if diff2 == 0:
|
|
157
|
+
return False
|
|
158
|
+
|
|
159
|
+
ratio = diff1 / diff2
|
|
160
|
+
fit_pct = 1 - flat_ratio
|
|
161
|
+
if ratio < 1:
|
|
162
|
+
same_height = ratio >= fit_pct
|
|
163
|
+
else:
|
|
164
|
+
same_height = ratio <= 1 / fit_pct
|
|
165
|
+
logger.debug(f"Pivot {pivot1.point.index} ({pivot1.point.price:.4f}) "
|
|
166
|
+
f"and {pivot2.point.index} ({pivot2.point.price:.4f}), "
|
|
167
|
+
f"ref_prices: {ref_prices:.4f}, ratio: {ratio:.4f}")
|
|
168
|
+
return same_height
|
|
169
|
+
|