oakscriptpy 0.1.0__py3-none-any.whl
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.
- oakscriptpy/__init__.py +93 -0
- oakscriptpy/_metadata.py +118 -0
- oakscriptpy/_types.py +185 -0
- oakscriptpy/_utils.py +145 -0
- oakscriptpy/adapters/__init__.py +5 -0
- oakscriptpy/adapters/simple_input.py +63 -0
- oakscriptpy/array.py +342 -0
- oakscriptpy/box.py +151 -0
- oakscriptpy/chartpoint.py +21 -0
- oakscriptpy/color.py +134 -0
- oakscriptpy/indicator.py +82 -0
- oakscriptpy/input_.py +38 -0
- oakscriptpy/inputs.py +170 -0
- oakscriptpy/label.py +110 -0
- oakscriptpy/lib/__init__.py +5 -0
- oakscriptpy/lib/zigzag.py +158 -0
- oakscriptpy/line.py +120 -0
- oakscriptpy/linefill.py +26 -0
- oakscriptpy/math_.py +184 -0
- oakscriptpy/matrix.py +1136 -0
- oakscriptpy/plot_.py +49 -0
- oakscriptpy/polyline.py +60 -0
- oakscriptpy/runtime.py +150 -0
- oakscriptpy/runtime_types.py +52 -0
- oakscriptpy/series.py +292 -0
- oakscriptpy/str_.py +166 -0
- oakscriptpy/ta.py +1795 -0
- oakscriptpy/ta_series.py +353 -0
- oakscriptpy/time_.py +22 -0
- oakscriptpy-0.1.0.dist-info/METADATA +120 -0
- oakscriptpy-0.1.0.dist-info/RECORD +32 -0
- oakscriptpy-0.1.0.dist-info/WHEEL +4 -0
oakscriptpy/str_.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""String namespace — mirrors PineScript str.* functions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re as _re
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def length(s: str) -> int:
|
|
10
|
+
return len(s)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def tostring(value: object, fmt: str | None = None) -> str:
|
|
14
|
+
if isinstance(value, (int, float)) and fmt:
|
|
15
|
+
decimals = len(fmt.split(".")[1]) if "." in fmt else 0
|
|
16
|
+
return f"{value:.{decimals}f}"
|
|
17
|
+
return str(value)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def tonumber(s: str) -> float | None:
|
|
21
|
+
try:
|
|
22
|
+
return float(s)
|
|
23
|
+
except (ValueError, TypeError):
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def substring(s: str, begin: int, end: int | None = None) -> str:
|
|
28
|
+
if end is None:
|
|
29
|
+
return s[begin:]
|
|
30
|
+
return s[begin:end]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def upper(s: str) -> str:
|
|
34
|
+
return s.upper()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def lower(s: str) -> str:
|
|
38
|
+
return s.lower()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def contains(source: str, sub: str) -> bool:
|
|
42
|
+
return sub in source
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def pos(source: str, sub: str) -> int:
|
|
46
|
+
return source.find(sub)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def replace(source: str, target: str, replacement: str, occurrence: int | None = None) -> str:
|
|
50
|
+
if occurrence == 0:
|
|
51
|
+
return source.replace(target, replacement, 1)
|
|
52
|
+
return source.replace(target, replacement)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def replace_all(source: str, target: str, replacement: str) -> str:
|
|
56
|
+
return source.replace(target, replacement)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def split(s: str, separator: str) -> list[str]:
|
|
60
|
+
return s.split(separator)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def concat(*strings: str) -> str:
|
|
64
|
+
return "".join(strings)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def format(format_str: str, *args: object) -> str:
|
|
68
|
+
result = format_str
|
|
69
|
+
for i, arg in enumerate(args):
|
|
70
|
+
result = result.replace(f"{{{i}}}", str(arg))
|
|
71
|
+
return result
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def startswith(source: str, prefix: str) -> bool:
|
|
75
|
+
return source.startswith(prefix)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def endswith(source: str, suffix: str) -> bool:
|
|
79
|
+
return source.endswith(suffix)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def char_at(s: str, position: int) -> str:
|
|
83
|
+
if 0 <= position < len(s):
|
|
84
|
+
return s[position]
|
|
85
|
+
return ""
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def trim(s: str) -> str:
|
|
89
|
+
return s.strip()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def trim_left(s: str) -> str:
|
|
93
|
+
return s.lstrip()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def trim_right(s: str) -> str:
|
|
97
|
+
return s.rstrip()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def match(source: str, regex: str) -> bool:
|
|
101
|
+
return bool(_re.search(regex, source))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def repeat(source: str, count: int, separator: str = "") -> str | None:
|
|
105
|
+
if source is None:
|
|
106
|
+
return None
|
|
107
|
+
if count <= 0:
|
|
108
|
+
return ""
|
|
109
|
+
return separator.join([source] * count)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def format_time(time_ms: int, fmt: str) -> str:
|
|
113
|
+
dt = datetime.fromtimestamp(time_ms / 1000, tz=timezone.utc)
|
|
114
|
+
|
|
115
|
+
month_names = [
|
|
116
|
+
"January", "February", "March", "April", "May", "June",
|
|
117
|
+
"July", "August", "September", "October", "November", "December",
|
|
118
|
+
]
|
|
119
|
+
month_names_short = [
|
|
120
|
+
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
121
|
+
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
year = dt.year
|
|
125
|
+
month = dt.month - 1
|
|
126
|
+
day = dt.day
|
|
127
|
+
hours = dt.hour
|
|
128
|
+
minutes = dt.minute
|
|
129
|
+
seconds = dt.second
|
|
130
|
+
|
|
131
|
+
hours12 = hours % 12 or 12
|
|
132
|
+
ampm = "AM" if hours < 12 else "PM"
|
|
133
|
+
|
|
134
|
+
replacements = [
|
|
135
|
+
("yyyy", str(year)),
|
|
136
|
+
("yy", str(year)[-2:]),
|
|
137
|
+
("MMMM", month_names[month]),
|
|
138
|
+
("MMM", month_names_short[month]),
|
|
139
|
+
("MM", f"{month + 1:02d}"),
|
|
140
|
+
("M", str(month + 1)),
|
|
141
|
+
("dd", f"{day:02d}"),
|
|
142
|
+
("d", str(day)),
|
|
143
|
+
("HH", f"{hours:02d}"),
|
|
144
|
+
("H", str(hours)),
|
|
145
|
+
("hh", f"{hours12:02d}"),
|
|
146
|
+
("h", str(hours12)),
|
|
147
|
+
("mm", f"{minutes:02d}"),
|
|
148
|
+
("m", str(minutes)),
|
|
149
|
+
("ss", f"{seconds:02d}"),
|
|
150
|
+
("s", str(seconds)),
|
|
151
|
+
("a", ampm),
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
# Two-pass replacement using unique tokens
|
|
155
|
+
tokens: list[str] = []
|
|
156
|
+
result = fmt
|
|
157
|
+
for i, (pattern, value) in enumerate(replacements):
|
|
158
|
+
token = f"\ufff0{i}\ufff1"
|
|
159
|
+
result = result.replace(pattern, token)
|
|
160
|
+
tokens.append(value)
|
|
161
|
+
|
|
162
|
+
for i, value in enumerate(tokens):
|
|
163
|
+
token = f"\ufff0{i}\ufff1"
|
|
164
|
+
result = result.replace(token, value)
|
|
165
|
+
|
|
166
|
+
return result
|