oakscriptpy 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.
Files changed (98) hide show
  1. oakscriptpy-0.1.0/.github/workflows/publish.yml +26 -0
  2. oakscriptpy-0.1.0/.gitignore +7 -0
  3. oakscriptpy-0.1.0/DEVLOG.md +81 -0
  4. oakscriptpy-0.1.0/PKG-INFO +120 -0
  5. oakscriptpy-0.1.0/README.md +99 -0
  6. oakscriptpy-0.1.0/logo.png +0 -0
  7. oakscriptpy-0.1.0/pyproject.toml +37 -0
  8. oakscriptpy-0.1.0/src/oakscriptpy/__init__.py +93 -0
  9. oakscriptpy-0.1.0/src/oakscriptpy/_metadata.py +118 -0
  10. oakscriptpy-0.1.0/src/oakscriptpy/_types.py +185 -0
  11. oakscriptpy-0.1.0/src/oakscriptpy/_utils.py +145 -0
  12. oakscriptpy-0.1.0/src/oakscriptpy/adapters/__init__.py +5 -0
  13. oakscriptpy-0.1.0/src/oakscriptpy/adapters/simple_input.py +63 -0
  14. oakscriptpy-0.1.0/src/oakscriptpy/array.py +342 -0
  15. oakscriptpy-0.1.0/src/oakscriptpy/box.py +151 -0
  16. oakscriptpy-0.1.0/src/oakscriptpy/chartpoint.py +21 -0
  17. oakscriptpy-0.1.0/src/oakscriptpy/color.py +134 -0
  18. oakscriptpy-0.1.0/src/oakscriptpy/indicator.py +82 -0
  19. oakscriptpy-0.1.0/src/oakscriptpy/input_.py +38 -0
  20. oakscriptpy-0.1.0/src/oakscriptpy/inputs.py +170 -0
  21. oakscriptpy-0.1.0/src/oakscriptpy/label.py +110 -0
  22. oakscriptpy-0.1.0/src/oakscriptpy/lib/__init__.py +5 -0
  23. oakscriptpy-0.1.0/src/oakscriptpy/lib/zigzag.py +158 -0
  24. oakscriptpy-0.1.0/src/oakscriptpy/line.py +120 -0
  25. oakscriptpy-0.1.0/src/oakscriptpy/linefill.py +26 -0
  26. oakscriptpy-0.1.0/src/oakscriptpy/math_.py +184 -0
  27. oakscriptpy-0.1.0/src/oakscriptpy/matrix.py +1136 -0
  28. oakscriptpy-0.1.0/src/oakscriptpy/plot_.py +49 -0
  29. oakscriptpy-0.1.0/src/oakscriptpy/polyline.py +60 -0
  30. oakscriptpy-0.1.0/src/oakscriptpy/runtime.py +150 -0
  31. oakscriptpy-0.1.0/src/oakscriptpy/runtime_types.py +52 -0
  32. oakscriptpy-0.1.0/src/oakscriptpy/series.py +292 -0
  33. oakscriptpy-0.1.0/src/oakscriptpy/str_.py +166 -0
  34. oakscriptpy-0.1.0/src/oakscriptpy/ta.py +1795 -0
  35. oakscriptpy-0.1.0/src/oakscriptpy/ta_series.py +353 -0
  36. oakscriptpy-0.1.0/src/oakscriptpy/time_.py +22 -0
  37. oakscriptpy-0.1.0/tests/__init__.py +0 -0
  38. oakscriptpy-0.1.0/tests/array/__init__.py +0 -0
  39. oakscriptpy-0.1.0/tests/array/test_drawing_objects.py +452 -0
  40. oakscriptpy-0.1.0/tests/array/test_final_functions.py +277 -0
  41. oakscriptpy-0.1.0/tests/array/test_new_functions.py +257 -0
  42. oakscriptpy-0.1.0/tests/array/test_percentile.py +260 -0
  43. oakscriptpy-0.1.0/tests/array/test_search_and_stats.py +303 -0
  44. oakscriptpy-0.1.0/tests/box/__init__.py +0 -0
  45. oakscriptpy-0.1.0/tests/box/test_box.py +292 -0
  46. oakscriptpy-0.1.0/tests/chartpoint/__init__.py +0 -0
  47. oakscriptpy-0.1.0/tests/chartpoint/test_chartpoint.py +156 -0
  48. oakscriptpy-0.1.0/tests/color/__init__.py +0 -0
  49. oakscriptpy-0.1.0/tests/color/test_components.py +172 -0
  50. oakscriptpy-0.1.0/tests/color/test_constants.py +125 -0
  51. oakscriptpy-0.1.0/tests/color/test_creation.py +110 -0
  52. oakscriptpy-0.1.0/tests/color/test_manipulation.py +75 -0
  53. oakscriptpy-0.1.0/tests/conftest.py +31 -0
  54. oakscriptpy-0.1.0/tests/indicator/__init__.py +0 -0
  55. oakscriptpy-0.1.0/tests/indicator/test_indicator.py +387 -0
  56. oakscriptpy-0.1.0/tests/label/__init__.py +0 -0
  57. oakscriptpy-0.1.0/tests/label/test_label.py +311 -0
  58. oakscriptpy-0.1.0/tests/line/__init__.py +0 -0
  59. oakscriptpy-0.1.0/tests/line/test_line.py +251 -0
  60. oakscriptpy-0.1.0/tests/linefill/__init__.py +0 -0
  61. oakscriptpy-0.1.0/tests/linefill/test_linefill.py +257 -0
  62. oakscriptpy-0.1.0/tests/math/__init__.py +0 -0
  63. oakscriptpy-0.1.0/tests/math/test_algebraic.py +166 -0
  64. oakscriptpy-0.1.0/tests/math/test_basic.py +224 -0
  65. oakscriptpy-0.1.0/tests/math/test_series_support.py +200 -0
  66. oakscriptpy-0.1.0/tests/math/test_sum_series.py +21 -0
  67. oakscriptpy-0.1.0/tests/math/test_trigonometric.py +188 -0
  68. oakscriptpy-0.1.0/tests/math/test_utility.py +150 -0
  69. oakscriptpy-0.1.0/tests/matrix/__init__.py +0 -0
  70. oakscriptpy-0.1.0/tests/matrix/test_foundational.py +525 -0
  71. oakscriptpy-0.1.0/tests/matrix/test_linear_algebra.py +837 -0
  72. oakscriptpy-0.1.0/tests/matrix/test_manipulation.py +999 -0
  73. oakscriptpy-0.1.0/tests/polyline/__init__.py +0 -0
  74. oakscriptpy-0.1.0/tests/polyline/test_polyline.py +318 -0
  75. oakscriptpy-0.1.0/tests/runtime/__init__.py +0 -0
  76. oakscriptpy-0.1.0/tests/runtime/test_adapters.py +182 -0
  77. oakscriptpy-0.1.0/tests/runtime/test_inputs.py +352 -0
  78. oakscriptpy-0.1.0/tests/runtime/test_runtime.py +310 -0
  79. oakscriptpy-0.1.0/tests/runtime/test_series.py +475 -0
  80. oakscriptpy-0.1.0/tests/str/__init__.py +0 -0
  81. oakscriptpy-0.1.0/tests/str/test_conversion.py +103 -0
  82. oakscriptpy-0.1.0/tests/str/test_formatting.py +108 -0
  83. oakscriptpy-0.1.0/tests/str/test_manipulation.py +92 -0
  84. oakscriptpy-0.1.0/tests/str/test_predicates.py +121 -0
  85. oakscriptpy-0.1.0/tests/str/test_search.py +108 -0
  86. oakscriptpy-0.1.0/tests/str/test_whitespace.py +157 -0
  87. oakscriptpy-0.1.0/tests/ta/__init__.py +0 -0
  88. oakscriptpy-0.1.0/tests/ta/test_ichimoku.py +204 -0
  89. oakscriptpy-0.1.0/tests/ta/test_new_functions.py +223 -0
  90. oakscriptpy-0.1.0/tests/ta/test_new_functions2.py +225 -0
  91. oakscriptpy-0.1.0/tests/ta/test_new_functions3.py +226 -0
  92. oakscriptpy-0.1.0/tests/ta/test_new_ta_functions.py +185 -0
  93. oakscriptpy-0.1.0/tests/ta/test_rsi.py +147 -0
  94. oakscriptpy-0.1.0/tests/ta/test_sma.py +37 -0
  95. oakscriptpy-0.1.0/tests/ta/test_supertrend.py +147 -0
  96. oakscriptpy-0.1.0/tests/ta/test_ta_series_integration.py +79 -0
  97. oakscriptpy-0.1.0/tests/ta/test_zigzag.py +281 -0
  98. oakscriptpy-0.1.0/tests/test_new_functions.py +107 -0
@@ -0,0 +1,26 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: astral-sh/setup-uv@v5
13
+ - run: uv sync --dev
14
+ - run: uv run pytest
15
+
16
+ publish:
17
+ needs: test
18
+ runs-on: ubuntu-latest
19
+ environment: pypi
20
+ permissions:
21
+ id-token: write
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: astral-sh/setup-uv@v5
25
+ - run: uv build
26
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,7 @@
1
+ .idea/
2
+ __pycache__/
3
+ *.pyc
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .tmp/
@@ -0,0 +1,81 @@
1
+ # DEVLOG
2
+
3
+ ## 2026-02-26 - Port oakscriptJS to oakscriptPy
4
+
5
+ ### Goal
6
+ Port the complete oakscriptJS TypeScript library (PineScript-like API) to Python, covering all 217+ functions across 13 namespaces.
7
+
8
+ ### Approach Taken
9
+ 7-phase implementation following dependency order:
10
+ 1. Foundation types & utils
11
+ 2. Core computation (ta, math, array, color, str, time, matrix)
12
+ 3. Drawing objects (line, box, label, linefill, chartpoint, polyline)
13
+ 4. Series + TA-Series (lazy evaluation, operator overloading)
14
+ 5. Runtime system (context, plot, hline, inputs, adapters)
15
+ 6. Infrastructure (indicator factory, input helpers, plot helpers, zigzag library)
16
+ 7. Package integration (__init__.py, re-exports, verification)
17
+
18
+ ### What Worked
19
+ - Parallel background agents for ta.py (1795 lines) and matrix.py (1136 lines) while writing smaller modules directly
20
+ - Python operator overloading for Series (`__add__`, `__radd__`, `__gt__`, etc.) maps naturally to the JS `.add()`, `.sub()`, `.gt()` methods
21
+ - `typing.Protocol` for adapter interfaces mirrors TS interfaces cleanly
22
+ - Trailing underscore naming (`math_.py`, `str_.py`, `time_.py`) avoids stdlib clashes, re-exported as `math`, `str`, `time` in `__init__.py`
23
+ - `range_`, `max_`, `min_` in ta.py avoid Python builtin clashes
24
+
25
+ ### Current State
26
+ - **Done**: All 7 phases complete, 6224 lines across 28 Python files
27
+ - **Verified**: Package imports, SMA/EMA calculations, Series operators, matrix operations, line interpolation, string functions, chart points, time functions, is_na/nz
28
+ - **Not yet done**: Series dual-mode support in math_.py (scalar functions work, Series support deferred)
29
+
30
+ ### Key Decisions
31
+ - `PineArray` = plain `list[T]` (no wrapper class)
32
+ - `PineMatrix` = `@dataclass` with `rows`, `columns`, `data: list[list[Any]]`
33
+ - NaN = `float('nan')`, NA = `None`, `is_na()` checks both
34
+ - Series logical ops as methods (`and_()`, `or_()`, `not_()`) since Python reserves keywords
35
+ - No external dependencies (pure Python)
36
+ - Python 3.11+ required (union type syntax)
37
+
38
+ ## 2026-02-26 - Port Jest tests to pytest (math, color, str, new_functions)
39
+
40
+ ### Goal
41
+ Port all Jest test files from oakscriptJS to Python pytest equivalents for math, color, str namespaces and new_functions.
42
+
43
+ ### Approach Taken
44
+ 1-to-1 file mapping from JS test files to Python test files. Adapted for Python-specific behavior differences (ValueError vs NaN for math domain errors, float formatting, Python slicing semantics, Unicode code points vs UTF-16 surrogate pairs).
45
+
46
+ ### What Worked
47
+ - Direct porting of all scalar math, trig, utility, color, and string tests
48
+ - Series-based math tests marked with `pytest.mark.skip` (56 tests)
49
+ - Adapted JS-specific edge cases to Python equivalents (e.g., `math.sqrt(-1)` raises ValueError in Python vs returning NaN in JS)
50
+
51
+ ### Files Created
52
+ - `tests/math/test_basic.py` (abs, ceil, floor, round, max, min, avg, sum)
53
+ - `tests/math/test_algebraic.py` (sqrt, pow, exp, log, log10)
54
+ - `tests/math/test_trigonometric.py` (sin, cos, tan, asin, acos, atan)
55
+ - `tests/math/test_utility.py` (toradians, todegrees, random, sign)
56
+ - `tests/math/test_series_support.py` (skipped - Series not implemented)
57
+ - `tests/math/test_sum_series.py` (skipped - Series not implemented)
58
+ - `tests/color/test_creation.py` (rgb, from_hex)
59
+ - `tests/color/test_components.py` (r, g, b, t)
60
+ - `tests/color/test_constants.py` (all named color constants)
61
+ - `tests/color/test_manipulation.py` (new_color)
62
+ - `tests/str/test_conversion.py` (length, tostring, tonumber)
63
+ - `tests/str/test_formatting.py` (split, concat, format)
64
+ - `tests/str/test_manipulation.py` (substring, upper, lower)
65
+ - `tests/str/test_predicates.py` (startswith, endswith, char_at)
66
+ - `tests/str/test_search.py` (contains, pos, replace)
67
+ - `tests/str/test_whitespace.py` (trim, trim_left, trim_right, match)
68
+ - `tests/test_new_functions.py` (color.new alias, replace_all, format_time)
69
+ - `__init__.py` in tests/, tests/math/, tests/color/, tests/str/
70
+
71
+ ### Current State
72
+ - **339 passed, 56 skipped** (all skipped are Series-based math tests)
73
+ - No failures
74
+
75
+ ### Key Decisions
76
+ - Python `math.sqrt(-1)` / `math.log(0)` raise ValueError (tests use `pytest.raises`), unlike JS which returns NaN/-Infinity
77
+ - Python `round(0.005, 2)` = 0.0 due to IEEE 754 float representation (adapted test expectation)
78
+ - Python `color.rgb(r,g,b,100)` produces `"rgba(..., 0.0)"` not `"rgba(..., 0)"` (float formatting)
79
+ - Python `str.split('', '')` raises ValueError (tested as such instead of returning `[]`)
80
+ - Python `substring` uses direct slicing (negative indices and begin>end behave differently from JS)
81
+ - Python counts Unicode code points, not UTF-16 units (emoji = 1 char, not 2)
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: oakscriptpy
3
+ Version: 0.1.0
4
+ Summary: PineScript-like API for technical analysis in Python
5
+ Project-URL: Homepage, https://github.com/deepentropy/oakscriptPy
6
+ Project-URL: Repository, https://github.com/deepentropy/oakscriptPy
7
+ Project-URL: Issues, https://github.com/deepentropy/oakscriptPy/issues
8
+ Author: deepentropy
9
+ License-Expression: MIT
10
+ Keywords: finance,pinescript,ta,technical-analysis,trading
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Financial and Insurance Industry
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Office/Business :: Financial :: Investment
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+
22
+ <p align="center">
23
+ <img src="./logo.png" width="150" />
24
+ </p>
25
+
26
+ <h1 align="center">OakScriptPy</h1>
27
+
28
+ <p align="center">
29
+ PineScript-like API for technical analysis in Python. Pure Python, zero dependencies.
30
+ </p>
31
+
32
+ ---
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install oakscriptpy
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ from oakscriptpy import ta, math, color, Series
44
+ from oakscriptpy._types import Bar
45
+
46
+ # Create bars
47
+ bars = [
48
+ Bar(time=1, open=10.0, high=12.0, low=9.0, close=11.0, volume=100.0),
49
+ Bar(time=2, open=11.0, high=13.0, low=10.0, close=12.0, volume=110.0),
50
+ Bar(time=3, open=12.0, high=14.0, low=11.0, close=13.0, volume=120.0),
51
+ # ...
52
+ ]
53
+
54
+ # Array-based TA
55
+ closes = [b.close for b in bars]
56
+ sma_values = ta.sma(closes, 3)
57
+ ema_values = ta.ema(closes, 3)
58
+ rsi_values = ta.rsi(closes, 14)
59
+
60
+ # Series-based TA (with operator overloading)
61
+ from oakscriptpy import ta as ta_series
62
+ close_series = Series.from_bars(bars, lambda b: b.close)
63
+ sma_series = ta_series.sma(close_series, 3)
64
+ ema_series = ta_series.ema(close_series, 3)
65
+
66
+ # Series arithmetic
67
+ spread = close_series - sma_series
68
+ doubled = close_series * 2
69
+ above_sma = close_series > sma_series
70
+ ```
71
+
72
+ ## Namespaces
73
+
74
+ | Namespace | Functions | Description |
75
+ |-----------|-----------|-------------|
76
+ | `ta` | 64 | Technical analysis (SMA, EMA, RSI, MACD, Bollinger Bands, Ichimoku, SuperTrend, ZigZag, etc.) |
77
+ | `math` | 26 | Mathematical functions (abs, ceil, floor, sqrt, pow, trig, etc.) |
78
+ | `array` | 42+ | Array manipulation (push, pop, sort, slice, binary_search, percentile, etc.) |
79
+ | `color` | 14 + 17 constants | Color creation and manipulation (rgb, from_hex, new_color, named constants) |
80
+ | `str` | 20+ | String functions (split, replace, substring, contains, match, etc.) |
81
+ | `time` | 2 | Time utilities (format_time) |
82
+ | `matrix` | 43 | Matrix operations (add, mult, det, inv, eigenvalues, eigenvectors, etc.) |
83
+ | `line` | 10 | Line drawing objects |
84
+ | `box` | 12 | Box drawing objects |
85
+ | `label` | 10 | Label drawing objects |
86
+ | `linefill` | 4 | Linefill functions |
87
+ | `chart_point` | 3 | Chart point functions |
88
+ | `polyline` | 5 | Polyline functions |
89
+
90
+ ## Series
91
+
92
+ The `Series` class provides lazy evaluation with Python operator overloading:
93
+
94
+ ```python
95
+ a = Series.from_bars(bars, lambda b: b.close)
96
+ b = Series.from_bars(bars, lambda b: b.open)
97
+
98
+ # Arithmetic: +, -, *, /, %
99
+ spread = a - b
100
+
101
+ # Comparison: >, >=, <, <=, eq(), neq()
102
+ bullish = a > b
103
+
104
+ # Logical: and_(), or_(), not_()
105
+ signal = bullish.and_(a > sma_series)
106
+
107
+ # History access
108
+ prev_close = a.offset(1)
109
+ ```
110
+
111
+ ## Tests
112
+
113
+ ```bash
114
+ uv run pytest
115
+ # 1,224 passed, 56 skipped
116
+ ```
117
+
118
+ ## License
119
+
120
+ MIT
@@ -0,0 +1,99 @@
1
+ <p align="center">
2
+ <img src="./logo.png" width="150" />
3
+ </p>
4
+
5
+ <h1 align="center">OakScriptPy</h1>
6
+
7
+ <p align="center">
8
+ PineScript-like API for technical analysis in Python. Pure Python, zero dependencies.
9
+ </p>
10
+
11
+ ---
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pip install oakscriptpy
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```python
22
+ from oakscriptpy import ta, math, color, Series
23
+ from oakscriptpy._types import Bar
24
+
25
+ # Create bars
26
+ bars = [
27
+ Bar(time=1, open=10.0, high=12.0, low=9.0, close=11.0, volume=100.0),
28
+ Bar(time=2, open=11.0, high=13.0, low=10.0, close=12.0, volume=110.0),
29
+ Bar(time=3, open=12.0, high=14.0, low=11.0, close=13.0, volume=120.0),
30
+ # ...
31
+ ]
32
+
33
+ # Array-based TA
34
+ closes = [b.close for b in bars]
35
+ sma_values = ta.sma(closes, 3)
36
+ ema_values = ta.ema(closes, 3)
37
+ rsi_values = ta.rsi(closes, 14)
38
+
39
+ # Series-based TA (with operator overloading)
40
+ from oakscriptpy import ta as ta_series
41
+ close_series = Series.from_bars(bars, lambda b: b.close)
42
+ sma_series = ta_series.sma(close_series, 3)
43
+ ema_series = ta_series.ema(close_series, 3)
44
+
45
+ # Series arithmetic
46
+ spread = close_series - sma_series
47
+ doubled = close_series * 2
48
+ above_sma = close_series > sma_series
49
+ ```
50
+
51
+ ## Namespaces
52
+
53
+ | Namespace | Functions | Description |
54
+ |-----------|-----------|-------------|
55
+ | `ta` | 64 | Technical analysis (SMA, EMA, RSI, MACD, Bollinger Bands, Ichimoku, SuperTrend, ZigZag, etc.) |
56
+ | `math` | 26 | Mathematical functions (abs, ceil, floor, sqrt, pow, trig, etc.) |
57
+ | `array` | 42+ | Array manipulation (push, pop, sort, slice, binary_search, percentile, etc.) |
58
+ | `color` | 14 + 17 constants | Color creation and manipulation (rgb, from_hex, new_color, named constants) |
59
+ | `str` | 20+ | String functions (split, replace, substring, contains, match, etc.) |
60
+ | `time` | 2 | Time utilities (format_time) |
61
+ | `matrix` | 43 | Matrix operations (add, mult, det, inv, eigenvalues, eigenvectors, etc.) |
62
+ | `line` | 10 | Line drawing objects |
63
+ | `box` | 12 | Box drawing objects |
64
+ | `label` | 10 | Label drawing objects |
65
+ | `linefill` | 4 | Linefill functions |
66
+ | `chart_point` | 3 | Chart point functions |
67
+ | `polyline` | 5 | Polyline functions |
68
+
69
+ ## Series
70
+
71
+ The `Series` class provides lazy evaluation with Python operator overloading:
72
+
73
+ ```python
74
+ a = Series.from_bars(bars, lambda b: b.close)
75
+ b = Series.from_bars(bars, lambda b: b.open)
76
+
77
+ # Arithmetic: +, -, *, /, %
78
+ spread = a - b
79
+
80
+ # Comparison: >, >=, <, <=, eq(), neq()
81
+ bullish = a > b
82
+
83
+ # Logical: and_(), or_(), not_()
84
+ signal = bullish.and_(a > sma_series)
85
+
86
+ # History access
87
+ prev_close = a.offset(1)
88
+ ```
89
+
90
+ ## Tests
91
+
92
+ ```bash
93
+ uv run pytest
94
+ # 1,224 passed, 56 skipped
95
+ ```
96
+
97
+ ## License
98
+
99
+ MIT
Binary file
@@ -0,0 +1,37 @@
1
+ [project]
2
+ name = "oakscriptpy"
3
+ version = "0.1.0"
4
+ description = "PineScript-like API for technical analysis in Python"
5
+ requires-python = ">=3.11"
6
+ dependencies = []
7
+ readme = "README.md"
8
+ license = "MIT"
9
+ authors = [{ name = "deepentropy" }]
10
+ keywords = ["pinescript", "technical-analysis", "trading", "finance", "ta"]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Intended Audience :: Developers",
14
+ "Intended Audience :: Financial and Insurance Industry",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Topic :: Office/Business :: Financial :: Investment",
20
+ ]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/deepentropy/oakscriptPy"
24
+ Repository = "https://github.com/deepentropy/oakscriptPy"
25
+ Issues = "https://github.com/deepentropy/oakscriptPy/issues"
26
+
27
+ [build-system]
28
+ requires = ["hatchling"]
29
+ build-backend = "hatchling.build"
30
+
31
+ [tool.hatch.build.targets.wheel]
32
+ packages = ["src/oakscriptpy"]
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ "pytest>=9.0.2",
37
+ ]
@@ -0,0 +1,93 @@
1
+ """OakScriptPy — PineScript-like API for technical analysis in Python."""
2
+ from __future__ import annotations
3
+
4
+ # Core namespaces (array-based functions)
5
+ from . import ta as ta_core
6
+ from . import math_ as math
7
+ from . import array
8
+ from . import str_ as str
9
+ from . import color
10
+ from . import time_ as time
11
+ from . import matrix
12
+
13
+ # Drawing object namespaces
14
+ from . import line
15
+ from . import box
16
+ from . import label
17
+ from . import linefill
18
+ from . import chartpoint as chart_point
19
+ from . import polyline
20
+
21
+ # Series class (self-contained, no context)
22
+ from .series import Series, BarData
23
+
24
+ # TA-Series namespace (Series-based wrappers)
25
+ from . import ta_series as ta
26
+
27
+ # Types
28
+ from ._types import (
29
+ Bar, Line as LineType, Box as BoxType, Label as LabelType,
30
+ Linefill as LinefillType, ChartPoint, Polyline as PolylineType,
31
+ Table, TableCell, Plot, HLine, OHLC, PineMatrix,
32
+ series_float, series_int, series_bool, series_string,
33
+ Source, color as color_type, na, xloc,
34
+ )
35
+
36
+ # Metadata types
37
+ from ._metadata import (
38
+ PlotOptions, HLineOptions, FillOptions, InputMetadata,
39
+ PlotMetadata, IndicatorMetadata, TimeValue, PlotData,
40
+ HLineData, FillData, IndicatorResult,
41
+ )
42
+
43
+ # Utilities
44
+ from ._utils import is_na, nz, ohlc_from_bars, get_close, get_high, get_low, get_open, get_source
45
+
46
+ # Runtime
47
+ from .runtime import (
48
+ set_context, clear_context, get_context,
49
+ register_calculate, recalculate,
50
+ plot, hline, clear_plots, get_active_plots,
51
+ )
52
+ from .runtime_types import OakScriptContext, OhlcvData, InputConfig
53
+
54
+ # Inputs
55
+ from .inputs import (
56
+ input_int, input_float, input_bool, input_string, input_source,
57
+ enable_auto_recalculate, disable_auto_recalculate, reset_inputs,
58
+ )
59
+
60
+ # Indicator infrastructure
61
+ from .indicator import indicator, IndicatorMetadataConfig, IndicatorContext, IndicatorInstance
62
+
63
+ # Input helper
64
+ from . import input_ as input
65
+
66
+ # Plot helper
67
+ from .plot_ import plot as plot_helper, create_plot, TimeValuePair, PlotResult
68
+
69
+ # Adapters
70
+ from .adapters import SimpleInputAdapter
71
+
72
+ # Libraries
73
+ from .lib import ZigZag, calculate_zigzag
74
+
75
+
76
+ def alertcondition(_condition: object = None, _title: str | None = None, _message: str | None = None) -> None:
77
+ """No-op stub for PineScript alertcondition() compatibility."""
78
+ pass
79
+
80
+
81
+ VERSION = "0.1.0"
82
+
83
+ info = {
84
+ "name": "OakScriptPy",
85
+ "version": VERSION,
86
+ "description": "PineScript-like API for technical analysis in Python",
87
+ "namespaces": {
88
+ "core": ["ta", "math", "array", "str", "color", "time", "matrix"],
89
+ "drawing": ["line", "box", "label", "linefill", "chart_point", "polyline"],
90
+ "runtime": ["set_context", "plot", "hline", "input_*"],
91
+ "indicator": ["indicator", "input", "plot_helper", "create_plot"],
92
+ },
93
+ }
@@ -0,0 +1,118 @@
1
+ """Indicator metadata types for oakscriptPy."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from typing import Any
7
+
8
+
9
+ PlotStyle = str # 'line' | 'stepline' | 'histogram' | 'area' | 'circles' | 'columns' | 'cross' | 'areabr' | 'steplinebr' | 'linebr'
10
+ LineStyle = str # 'solid' | 'dashed' | 'dotted'
11
+ PlotDisplay = str # 'all' | 'none' | 'data_window' | 'status_line' | 'pane'
12
+ InputType = str # 'int' | 'float' | 'bool' | 'string' | 'source' | 'color' | 'timeframe' | 'session'
13
+
14
+
15
+ @dataclass
16
+ class PlotOptions:
17
+ title: str | None = None
18
+ color: str | None = None
19
+ linewidth: int | None = None
20
+ style: str | None = None
21
+ trackprice: bool | None = None
22
+ histbase: float | None = None
23
+ offset: int | None = None
24
+ join: bool | None = None
25
+ editable: bool | None = None
26
+ display: str | None = None
27
+ transp: int | None = None
28
+
29
+
30
+ @dataclass
31
+ class HLineOptions:
32
+ title: str | None = None
33
+ color: str | None = None
34
+ linestyle: str | None = None
35
+ linewidth: int | None = None
36
+ editable: bool | None = None
37
+
38
+
39
+ @dataclass
40
+ class FillOptions:
41
+ color: str | None = None
42
+ transp: int | None = None
43
+ title: str | None = None
44
+ editable: bool | None = None
45
+ fillgaps: bool | None = None
46
+
47
+
48
+ @dataclass
49
+ class InputMetadata:
50
+ type: str
51
+ name: str
52
+ title: str
53
+ defval: Any
54
+ minval: float | None = None
55
+ maxval: float | None = None
56
+ step: float | None = None
57
+ tooltip: str | None = None
58
+ inline: str | None = None
59
+ group: str | None = None
60
+ options: list[Any] | None = None
61
+ confirm: bool | None = None
62
+
63
+
64
+ @dataclass
65
+ class PlotMetadata:
66
+ var_name: str
67
+ title: str
68
+ color: str
69
+ linewidth: int
70
+ style: str
71
+
72
+
73
+ @dataclass
74
+ class IndicatorMetadata:
75
+ title: str
76
+ shorttitle: str | None = None
77
+ overlay: bool = False
78
+ precision: int | None = None
79
+ format: str | None = None
80
+ timeframe: str | None = None
81
+ timeframe_gaps: bool | None = None
82
+ inputs: list[InputMetadata] | None = None
83
+ plots: list[PlotMetadata] | None = None
84
+
85
+
86
+ @dataclass
87
+ class TimeValue:
88
+ time: Any
89
+ value: float
90
+ color: str | None = None
91
+
92
+
93
+ @dataclass
94
+ class PlotData:
95
+ data: list[TimeValue]
96
+ options: PlotOptions | None = None
97
+
98
+
99
+ @dataclass
100
+ class HLineData:
101
+ value: float
102
+ options: HLineOptions | None = None
103
+
104
+
105
+ @dataclass
106
+ class FillData:
107
+ plot1: int | str
108
+ plot2: int | str
109
+ options: FillOptions | None = None
110
+ colors: list[str] | None = None
111
+
112
+
113
+ @dataclass
114
+ class IndicatorResult:
115
+ metadata: IndicatorMetadata
116
+ plots: dict[str, list[TimeValue]]
117
+ hlines: list[HLineData] | None = None
118
+ fills: list[FillData] | None = None