vnai 0.1.3__py3-none-any.whl → 2.3.7__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.
- vnai/__init__.py +304 -292
- vnai/beam/__init__.py +26 -0
- vnai/beam/auth.py +312 -0
- vnai/beam/fundamental.py +168 -0
- vnai/beam/metrics.py +167 -0
- vnai/beam/patching.py +223 -0
- vnai/beam/pulse.py +79 -0
- vnai/beam/quota.py +403 -0
- vnai/beam/sync.py +87 -0
- vnai/flow/__init__.py +2 -0
- vnai/flow/queue.py +100 -0
- vnai/flow/relay.py +347 -0
- vnai/scope/__init__.py +11 -0
- vnai/scope/device.py +315 -0
- vnai/scope/lc_integration.py +351 -0
- vnai/scope/license.py +197 -0
- vnai/scope/profile.py +599 -0
- vnai/scope/promo.py +389 -0
- vnai/scope/state.py +155 -0
- vnai-2.3.7.dist-info/METADATA +21 -0
- vnai-2.3.7.dist-info/RECORD +23 -0
- {vnai-0.1.3.dist-info → vnai-2.3.7.dist-info}/WHEEL +1 -1
- vnai-0.1.3.dist-info/METADATA +0 -20
- vnai-0.1.3.dist-info/RECORD +0 -5
- {vnai-0.1.3.dist-info → vnai-2.3.7.dist-info}/top_level.txt +0 -0
vnai/__init__.py
CHANGED
|
@@ -1,315 +1,327 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import pathlib
|
|
3
|
-
import importlib.metadata
|
|
4
|
-
import requests
|
|
5
|
-
import psutil
|
|
6
|
-
import platform
|
|
7
|
-
import uuid
|
|
8
|
-
import sys
|
|
9
|
-
import socket
|
|
10
3
|
import json
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Chi tiết:\n
|
|
27
|
-
- Giấy phép sử dụng phần mềm: https://vnstocks.com/docs/tai-lieu/giay-phep-su-dung
|
|
28
|
-
- Chính sách quyền riêng tư: https://vnstocks.com/docs/tai-lieu/chinh-sach-quyen-rieng-tu
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
class VnstockInitializer:
|
|
32
|
-
def __init__(self, target, tc=TERMS_AND_CONDITIONS):
|
|
33
|
-
self.terms_and_conditions = tc
|
|
34
|
-
self.home_dir = HOME_DIR
|
|
35
|
-
self.project_dir = PROJECT_DIR
|
|
36
|
-
self.id_dir = ID_DIR
|
|
37
|
-
self.terms_file_path = TC_PATH
|
|
38
|
-
self.env_config = ID_DIR / "environment.json"
|
|
39
|
-
self.RH = 'asejruyy^&%$#W2vX>NfwrevDRESWR'
|
|
40
|
-
self.LH = 'YMAnhuytr%$59u90y7j-mjhgvyFTfbiuUYH'
|
|
4
|
+
import time
|
|
5
|
+
import threading
|
|
6
|
+
import functools
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Optional
|
|
9
|
+
import pandas as pd
|
|
10
|
+
TC_VAR ="ACCEPT_TC"
|
|
11
|
+
TC_VAL ="tôi đồng ý"
|
|
12
|
+
TC_PATH = pathlib.Path.home() /".vnstock" /"id" /"terms_agreement.txt"
|
|
13
|
+
TERMS_AND_CONDITIONS ="""
|
|
14
|
+
Khi tiếp tục sử dụng Vnstock, bạn xác nhận rằng bạn đã đọc, hiểu và đồng ý với Chính sách quyền riêng tư và Điều khoản, điều kiện về giấy phép sử dụng Vnstock.
|
|
15
|
+
Chi tiết:
|
|
16
|
+
- Giấy phép sử dụng phần mềm: https://vnstocks.com/onboard/giay-phep-su-dung
|
|
17
|
+
- Chính sách quyền riêng tư: https://vnstocks.com/onboard/chinh-sach-quyen-rieng-tu
|
|
18
|
+
"""
|
|
41
19
|
|
|
42
|
-
|
|
20
|
+
class Core:
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.initialized = False
|
|
23
|
+
self.webhook_url = None
|
|
24
|
+
self.init_time = datetime.now().isoformat()
|
|
25
|
+
self.home_dir = pathlib.Path.home()
|
|
26
|
+
self.project_dir = self.home_dir /".vnstock"
|
|
27
|
+
self.id_dir = self.project_dir /'id'
|
|
28
|
+
self.terms_file_path = TC_PATH
|
|
29
|
+
self.system_info = None
|
|
43
30
|
self.project_dir.mkdir(exist_ok=True)
|
|
44
31
|
self.id_dir.mkdir(exist_ok=True)
|
|
45
|
-
self.
|
|
46
|
-
|
|
47
|
-
kb = (str(self.project_dir).split(lmt)[-1] + str(self.id_dir).split(lmt)[-1] + str(self.terms_file_path).split(lmt)[-1]).ljust(32)[:32].encode('utf-8')
|
|
48
|
-
kb64 = base64.urlsafe_b64encode(kb)
|
|
49
|
-
self.cph = Fernet(kb64)
|
|
32
|
+
self.initialize()
|
|
50
33
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# Environment (modify to detect your specific frameworks)
|
|
34
|
+
def initialize(self):
|
|
35
|
+
if self.initialized:
|
|
36
|
+
return True
|
|
37
|
+
if not self._check_terms():
|
|
38
|
+
self._accept_terms()
|
|
39
|
+
from vnai.scope.profile import inspector
|
|
40
|
+
inspector.setup_vnstock_environment()
|
|
59
41
|
try:
|
|
60
|
-
from
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
environment = "Jupyter"
|
|
68
|
-
except (ImportError, AttributeError):
|
|
69
|
-
# Fallback if IPython isn't installed or other checks fail
|
|
70
|
-
if sys.stdout.isatty():
|
|
71
|
-
environment = "Terminal"
|
|
42
|
+
from vnai.scope.device import device_registry
|
|
43
|
+
vnstock_version = getattr(__import__('vnstock'),
|
|
44
|
+
'__version__','0.0.1')
|
|
45
|
+
if device_registry.needs_reregistration(vnstock_version):
|
|
46
|
+
system_info = inspector.examine()
|
|
47
|
+
device_registry.register(system_info, vnstock_version)
|
|
48
|
+
self.system_info = system_info
|
|
72
49
|
else:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# Memory information
|
|
100
|
-
ram_total = psutil.virtual_memory().total / (1024**3) # GB
|
|
101
|
-
ram_available = psutil.virtual_memory().available / (1024**3) # GB
|
|
102
|
-
|
|
103
|
-
hostname = socket.gethostname()
|
|
104
|
-
IPAddr = socket.gethostbyname(hostname)
|
|
105
|
-
|
|
106
|
-
mac = ':'.join(['{:02x}'.format((uuid.getnode() >> elements) & 0xff) for elements in range(0, 2 * 6, 2)])
|
|
107
|
-
|
|
108
|
-
# Combine information into a dictionary
|
|
109
|
-
info = {
|
|
110
|
-
"uuid": machine_id,
|
|
111
|
-
"environment": environment,
|
|
112
|
-
"hosting_service": hosting_service,
|
|
113
|
-
"python_version": platform.python_version(),
|
|
114
|
-
"os_name": os_info.system,
|
|
115
|
-
"os_version": os_info.version,
|
|
116
|
-
"machine": os_info.machine,
|
|
117
|
-
"cpu_model": cpu_arch,
|
|
118
|
-
"cpu_cores": cpu_cores,
|
|
119
|
-
"cpu_logical_cores": cpu_logical_cores,
|
|
120
|
-
"ram_total": round(ram_total, 1),
|
|
121
|
-
"ram_available": round(ram_available, 1),
|
|
122
|
-
"local_ip": IPAddr,
|
|
123
|
-
"mac_address": mac,
|
|
124
|
-
}
|
|
50
|
+
self.system_info = device_registry.get_registry()
|
|
51
|
+
except Exception as e:
|
|
52
|
+
import logging
|
|
53
|
+
logger = logging.getLogger(__name__)
|
|
54
|
+
msg =f"Device registration failed: {e}. Using fallback."
|
|
55
|
+
logger.warning(msg)
|
|
56
|
+
self.system_info = inspector.examine()
|
|
57
|
+
from vnai.scope.promo import ContentManager
|
|
58
|
+
manager = ContentManager()
|
|
59
|
+
if manager.is_paid_user is not True:
|
|
60
|
+
from vnai.scope.promo import present
|
|
61
|
+
present()
|
|
62
|
+
from vnai.scope.state import record
|
|
63
|
+
record("initialization", {"timestamp": datetime.now().isoformat()})
|
|
64
|
+
from vnai.flow.relay import conduit
|
|
65
|
+
conduit.queue({
|
|
66
|
+
"type":"system_info",
|
|
67
|
+
"data": {
|
|
68
|
+
"commercial": inspector.detect_commercial_usage(),
|
|
69
|
+
"packages": inspector.scan_packages()
|
|
70
|
+
}
|
|
71
|
+
}, priority="high")
|
|
72
|
+
self.initialized = True
|
|
73
|
+
_trigger_patching_after_init()
|
|
74
|
+
return True
|
|
125
75
|
|
|
126
|
-
|
|
76
|
+
def _check_terms(self):
|
|
77
|
+
return os.path.exists(self.terms_file_path)
|
|
127
78
|
|
|
128
|
-
def
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"""
|
|
132
|
-
print(self.terms_and_conditions)
|
|
133
|
-
|
|
134
|
-
# check if os.environ[TC_VAR] exist and equal to tôi đồng ý
|
|
79
|
+
def _accept_terms(self):
|
|
80
|
+
from vnai.scope.profile import inspector
|
|
81
|
+
system_info = inspector.examine()
|
|
135
82
|
if TC_VAR in os.environ and os.environ[TC_VAR] == TC_VAL:
|
|
136
|
-
|
|
83
|
+
os.environ[TC_VAR] = TC_VAL
|
|
137
84
|
else:
|
|
138
|
-
response = TC_VAL
|
|
139
85
|
os.environ[TC_VAR] = TC_VAL
|
|
86
|
+
now = datetime.now()
|
|
87
|
+
machine_id = system_info['machine_id']
|
|
88
|
+
signed_agreement = (
|
|
89
|
+
f"Người dùng có mã nhận dạng {machine_id} "
|
|
90
|
+
f"đã chấp nhận điều khoản & điều kiện sử dụng Vnstock "
|
|
91
|
+
f"lúc {now.isoformat()}\n\n"
|
|
92
|
+
f"{TERMS_AND_CONDITIONS}"
|
|
93
|
+
)
|
|
94
|
+
with open(self.terms_file_path,"w", encoding="utf-8") as f:
|
|
95
|
+
f.write(signed_agreement)
|
|
96
|
+
env_file = self.id_dir /"environment.json"
|
|
97
|
+
env_data = {
|
|
98
|
+
"accepted_agreement": True,
|
|
99
|
+
"timestamp": now.isoformat(),
|
|
100
|
+
"machine_id": machine_id
|
|
101
|
+
}
|
|
102
|
+
with open(env_file,"w") as f:
|
|
103
|
+
json.dump(env_data, f)
|
|
104
|
+
return True
|
|
105
|
+
|
|
106
|
+
def status(self):
|
|
107
|
+
from vnai.beam.pulse import monitor
|
|
108
|
+
from vnai.scope.state import tracker
|
|
109
|
+
return {
|
|
110
|
+
"initialized": self.initialized,
|
|
111
|
+
"health": monitor.report(),
|
|
112
|
+
"metrics": tracker.get_metrics()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
def configure_privacy(self, level="standard"):
|
|
116
|
+
from vnai.scope.state import tracker
|
|
117
|
+
return tracker.setup_privacy(level)
|
|
118
|
+
_core_instance = None
|
|
119
|
+
_core_lock = threading.Lock()
|
|
120
|
+
|
|
121
|
+
def _get_core():
|
|
122
|
+
global _core_instance
|
|
123
|
+
if _core_instance is None:
|
|
124
|
+
with _core_lock:
|
|
125
|
+
if _core_instance is None:
|
|
126
|
+
_core_instance = Core()
|
|
127
|
+
return _core_instance
|
|
128
|
+
|
|
129
|
+
def tc_init():
|
|
130
|
+
return _get_core().initialize()
|
|
131
|
+
|
|
132
|
+
def setup():
|
|
133
|
+
return _get_core().initialize()
|
|
134
|
+
|
|
135
|
+
def optimize_execution(resource_type="default"):
|
|
136
|
+
def decorator(func):
|
|
137
|
+
_optimized_func = [None]
|
|
138
|
+
@functools.wraps(func)
|
|
139
|
+
|
|
140
|
+
def wrapper(*args, **kwargs):
|
|
141
|
+
if _optimized_func[0] is None:
|
|
142
|
+
from vnai.beam.quota import optimize
|
|
143
|
+
actual_decorator = optimize(resource_type)
|
|
144
|
+
_optimized_func[0] = actual_decorator(func)
|
|
145
|
+
return _optimized_func[0](*args, **kwargs)
|
|
146
|
+
return wrapper
|
|
147
|
+
return decorator
|
|
148
|
+
|
|
149
|
+
def agg_execution(resource_type="default"):
|
|
150
|
+
def decorator(func):
|
|
151
|
+
_optimized_func = [None]
|
|
152
|
+
@functools.wraps(func)
|
|
153
|
+
|
|
154
|
+
def wrapper(*args, **kwargs):
|
|
155
|
+
if _optimized_func[0] is None:
|
|
156
|
+
from vnai.beam.quota import optimize
|
|
157
|
+
actual_decorator = optimize(resource_type, ad_cooldown=1500,
|
|
158
|
+
content_trigger_threshold=100000)
|
|
159
|
+
_optimized_func[0] = actual_decorator(func)
|
|
160
|
+
return _optimized_func[0](*args, **kwargs)
|
|
161
|
+
return wrapper
|
|
162
|
+
return decorator
|
|
140
163
|
|
|
141
|
-
|
|
142
|
-
|
|
164
|
+
def measure_performance(module_type="function"):
|
|
165
|
+
def decorator(func):
|
|
166
|
+
_captured_func = [None]
|
|
167
|
+
@functools.wraps(func)
|
|
168
|
+
|
|
169
|
+
def wrapper(*args, **kwargs):
|
|
170
|
+
if _captured_func[0] is None:
|
|
171
|
+
from vnai.beam.metrics import capture
|
|
172
|
+
actual_decorator = capture(module_type)
|
|
173
|
+
_captured_func[0] = actual_decorator(func)
|
|
174
|
+
return _captured_func[0](*args, **kwargs)
|
|
175
|
+
return wrapper
|
|
176
|
+
return decorator
|
|
177
|
+
|
|
178
|
+
def accept_license_terms(terms_text=None):
|
|
179
|
+
if terms_text is None:
|
|
180
|
+
terms_text = TERMS_AND_CONDITIONS
|
|
181
|
+
from vnai.scope.profile import inspector
|
|
182
|
+
system_info = inspector.examine()
|
|
183
|
+
terms_file_path = (
|
|
184
|
+
pathlib.Path.home() /".vnstock" /"id" /
|
|
185
|
+
"terms_agreement.txt"
|
|
186
|
+
)
|
|
187
|
+
os.makedirs(os.path.dirname(terms_file_path), exist_ok=True)
|
|
188
|
+
now = datetime.now()
|
|
189
|
+
machine_id = system_info['machine_id']
|
|
190
|
+
with open(terms_file_path,"w", encoding="utf-8") as f:
|
|
191
|
+
f.write(f"Người dùng có mã nhận dạng {machine_id} "
|
|
192
|
+
f"đã chấp nhận lúc {now.isoformat()}\n\n")
|
|
193
|
+
f.write(terms_text)
|
|
194
|
+
return True
|
|
195
|
+
|
|
196
|
+
def accept_vnstock_terms():
|
|
197
|
+
from vnai.scope.profile import inspector
|
|
198
|
+
system_info = inspector.examine()
|
|
199
|
+
home_dir = pathlib.Path.home()
|
|
200
|
+
project_dir = home_dir /".vnstock"
|
|
201
|
+
project_dir.mkdir(exist_ok=True)
|
|
202
|
+
id_dir = project_dir /'id'
|
|
203
|
+
id_dir.mkdir(exist_ok=True)
|
|
204
|
+
env_file = id_dir /"environment.json"
|
|
205
|
+
env_data = {
|
|
206
|
+
"accepted_agreement": True,
|
|
207
|
+
"timestamp": datetime.now().isoformat(),
|
|
208
|
+
"machine_id": system_info['machine_id']
|
|
209
|
+
}
|
|
210
|
+
try:
|
|
211
|
+
with open(env_file,"w") as f:
|
|
212
|
+
json.dump(env_data, f)
|
|
213
|
+
terms_file = id_dir /"terms_agreement.txt"
|
|
143
214
|
now = datetime.now()
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
except importlib.metadata.PackageNotFoundError:
|
|
151
|
-
# print("Package 'vnstock' not found")
|
|
152
|
-
pass
|
|
153
|
-
|
|
154
|
-
# parse HARDWARE to string to store in the file
|
|
155
|
-
signed_aggreement = f"MÔ TẢ:\nNgười dùng có mã nhận dạng {HARDWARE['uuid']} đã chấp nhận điều khoản & điều kiện sử dụng Vnstock lúc {now}\n---\n\nTHÔNG TIN THIẾT BỊ: {str(HARDWARE)}\n\nĐính kèm bản sao nội dung bạn đã đọc, hiểu rõ và đồng ý dưới đây:\n{self.terms_and_conditions}"
|
|
156
|
-
|
|
157
|
-
# Store the acceptance
|
|
158
|
-
with open(self.terms_file_path, "w", encoding="utf-8") as f:
|
|
159
|
-
f.write(signed_aggreement)
|
|
215
|
+
machine_id = system_info['machine_id']
|
|
216
|
+
with open(terms_file,"w", encoding="utf-8") as f:
|
|
217
|
+
f.write(f"Người dùng có mã nhận dạng {machine_id} "
|
|
218
|
+
f"đã chấp nhận lúc {now.isoformat()}\n\n")
|
|
219
|
+
f.write(TERMS_AND_CONDITIONS)
|
|
220
|
+
print("Vnstock terms accepted successfully.")
|
|
160
221
|
return True
|
|
222
|
+
except Exception as e:
|
|
223
|
+
print(f"Error accepting terms: {e}")
|
|
224
|
+
return False
|
|
225
|
+
|
|
226
|
+
def configure_privacy(level="standard"):
|
|
227
|
+
from vnai.scope.state import tracker
|
|
228
|
+
return tracker.setup_privacy(level)
|
|
229
|
+
|
|
230
|
+
def check_commercial_usage():
|
|
231
|
+
from vnai.scope.profile import inspector
|
|
232
|
+
return inspector.detect_commercial_usage()
|
|
161
233
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
234
|
+
def authenticate_for_persistence():
|
|
235
|
+
from vnai.scope.profile import inspector
|
|
236
|
+
return inspector.get_or_create_user_id()
|
|
237
|
+
|
|
238
|
+
def get_user_tier():
|
|
239
|
+
try:
|
|
240
|
+
from vnai.beam.auth import authenticator
|
|
241
|
+
return authenticator.get_tier_info()
|
|
242
|
+
except Exception as e:
|
|
243
|
+
return {
|
|
244
|
+
"tier":"guest",
|
|
245
|
+
"description":"Khách (không có API key)",
|
|
246
|
+
"limits": {"per_minute": 20,"per_hour": 1200},
|
|
247
|
+
"error": str(e)
|
|
175
248
|
}
|
|
176
249
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
250
|
+
def refresh_tier_cache():
|
|
251
|
+
try:
|
|
252
|
+
from vnai.beam.auth import authenticator
|
|
253
|
+
authenticator.get_tier(force_refresh=True)
|
|
254
|
+
return True
|
|
255
|
+
except Exception:
|
|
256
|
+
return False
|
|
257
|
+
|
|
258
|
+
def setup_api_key(api_key):
|
|
259
|
+
from vnai.beam.auth import authenticator
|
|
260
|
+
return authenticator.setup_api_key(api_key)
|
|
261
|
+
|
|
262
|
+
def get_api_key():
|
|
263
|
+
from vnai.beam.auth import authenticator
|
|
264
|
+
return authenticator.get_api_key()
|
|
265
|
+
|
|
266
|
+
def remove_api_key():
|
|
267
|
+
from vnai.beam.auth import authenticator
|
|
268
|
+
return authenticator.remove_api_key()
|
|
269
|
+
|
|
270
|
+
def check_api_key_status():
|
|
271
|
+
from vnai.beam.auth import authenticator
|
|
272
|
+
return authenticator.check_api_key_status()
|
|
180
273
|
|
|
274
|
+
def print_api_key_help():
|
|
275
|
+
from vnai.beam.auth import authenticator
|
|
276
|
+
return authenticator.print_help()
|
|
277
|
+
|
|
278
|
+
def get_quota_status(api_key):
|
|
279
|
+
from vnai.beam.quota_endpoint import quota_endpoint
|
|
280
|
+
return quota_endpoint.get_quota_status(api_key)
|
|
281
|
+
|
|
282
|
+
def get_tier_info():
|
|
283
|
+
from vnai.beam.quota_endpoint import quota_endpoint
|
|
284
|
+
return quota_endpoint.get_tier_info()
|
|
285
|
+
|
|
286
|
+
def check_quota_available(api_key):
|
|
287
|
+
from vnai.beam.quota_endpoint import quota_endpoint
|
|
288
|
+
return quota_endpoint.check_quota(api_key)
|
|
289
|
+
|
|
290
|
+
def get_quota_metadata(api_key):
|
|
291
|
+
from vnai.beam.quota_endpoint import quota_endpoint
|
|
292
|
+
return quota_endpoint.get_metadata(api_key)
|
|
293
|
+
|
|
294
|
+
def record_api_usage(api_key, amount=1):
|
|
295
|
+
from vnai.beam.quota_endpoint import quota_endpoint
|
|
296
|
+
return quota_endpoint.record_usage(api_key, amount)
|
|
297
|
+
|
|
298
|
+
def balance_sheet(symbol: str, source: str ='vci', period: str ='year',
|
|
299
|
+
lang: Optional[str] ='en', show_log: bool = False) -> pd.DataFrame:
|
|
300
|
+
_ensure_patches_applied()
|
|
301
|
+
from vnai.beam.fundamental import balance_sheet as get_balance_sheet
|
|
302
|
+
return get_balance_sheet(symbol, source=source, period=period, lang=lang, show_log=show_log)
|
|
303
|
+
|
|
304
|
+
def income_statement(symbol: str, source: str ='vci', period: str ='year',
|
|
305
|
+
lang: Optional[str] ='en', show_log: bool = False) -> pd.DataFrame:
|
|
306
|
+
_ensure_patches_applied()
|
|
307
|
+
from vnai.beam.fundamental import income_statement as get_income_statement
|
|
308
|
+
return get_income_statement(symbol, source=source, period=period, lang=lang, show_log=show_log)
|
|
309
|
+
|
|
310
|
+
def cash_flow(symbol, source='vci', period='year', lang='en', show_log=False):
|
|
311
|
+
_ensure_patches_applied()
|
|
312
|
+
from vnai.beam.fundamental import cash_flow as get_cash_flow
|
|
313
|
+
return get_cash_flow(symbol, source=source, period=period, lang=lang, show_log=show_log)
|
|
314
|
+
_patches_initialized = False
|
|
315
|
+
|
|
316
|
+
def _ensure_patches_applied():
|
|
317
|
+
global _patches_initialized
|
|
318
|
+
if not _patches_initialized:
|
|
181
319
|
try:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
"""
|
|
188
|
-
Checks if terms and conditions are accepted.
|
|
189
|
-
"""
|
|
190
|
-
if not self.env_config.exists() or not self.terms_file_path.exists():
|
|
191
|
-
# If not, ask for acceptance
|
|
192
|
-
accepted = self.show_terms_and_conditions()
|
|
193
|
-
if not accepted:
|
|
194
|
-
raise SystemExit("Điều khoản và điều kiện không được chấp nhận. Không thể tiếp tục.")
|
|
195
|
-
else:
|
|
196
|
-
self.log_analytics_data()
|
|
197
|
-
|
|
198
|
-
def packages_installed(self):
|
|
199
|
-
"""
|
|
200
|
-
Checks installed packages and returns a dictionary.
|
|
201
|
-
"""
|
|
202
|
-
# Define package mapping
|
|
203
|
-
package_mapping = {
|
|
204
|
-
"vnstock_family": [
|
|
205
|
-
"vnstock",
|
|
206
|
-
"vnstock3",
|
|
207
|
-
"vnstock_ezchart",
|
|
208
|
-
"vnstock_data_pro"
|
|
209
|
-
"vnstock_market_data_pipeline",
|
|
210
|
-
"vnstock_ta",
|
|
211
|
-
"vnii",
|
|
212
|
-
"vnai",
|
|
213
|
-
],
|
|
214
|
-
"analytics": [
|
|
215
|
-
"openbb",
|
|
216
|
-
"pandas_ta"
|
|
217
|
-
],
|
|
218
|
-
"static_charts": [
|
|
219
|
-
"matplotlib",
|
|
220
|
-
"seaborn",
|
|
221
|
-
"altair"
|
|
222
|
-
],
|
|
223
|
-
"dashboard": [
|
|
224
|
-
"streamlit",
|
|
225
|
-
"voila",
|
|
226
|
-
"panel",
|
|
227
|
-
"shiny",
|
|
228
|
-
"dash",
|
|
229
|
-
],
|
|
230
|
-
"interactive_charts": [
|
|
231
|
-
"mplfinance",
|
|
232
|
-
"plotly",
|
|
233
|
-
"plotline",
|
|
234
|
-
"bokeh",
|
|
235
|
-
"pyecharts",
|
|
236
|
-
"highcharts-core",
|
|
237
|
-
"highcharts-stock",
|
|
238
|
-
"mplchart",
|
|
239
|
-
],
|
|
240
|
-
"datafeed": [
|
|
241
|
-
"yfinance",
|
|
242
|
-
"alpha_vantage",
|
|
243
|
-
"pandas-datareader",
|
|
244
|
-
"investpy",
|
|
245
|
-
],
|
|
246
|
-
"official_api": [
|
|
247
|
-
"ssi-fc-data",
|
|
248
|
-
"ssi-fctrading"
|
|
249
|
-
],
|
|
250
|
-
"risk_return": [
|
|
251
|
-
"pyfolio",
|
|
252
|
-
"empyrical",
|
|
253
|
-
"quantstats",
|
|
254
|
-
"financetoolkit",
|
|
255
|
-
],
|
|
256
|
-
"machine_learning": [
|
|
257
|
-
"scipy",
|
|
258
|
-
"sklearn",
|
|
259
|
-
"statsmodels",
|
|
260
|
-
"pytorch",
|
|
261
|
-
"tensorflow",
|
|
262
|
-
"keras",
|
|
263
|
-
"xgboost"
|
|
264
|
-
],
|
|
265
|
-
"indicators": [
|
|
266
|
-
"stochastic",
|
|
267
|
-
"talib",
|
|
268
|
-
"tqdm",
|
|
269
|
-
"finta",
|
|
270
|
-
"financetoolkit",
|
|
271
|
-
"tulipindicators"
|
|
272
|
-
],
|
|
273
|
-
"backtesting": [
|
|
274
|
-
"vectorbt",
|
|
275
|
-
"backtesting",
|
|
276
|
-
"bt",
|
|
277
|
-
"zipline",
|
|
278
|
-
"pyalgotrade",
|
|
279
|
-
"backtrader",
|
|
280
|
-
"pybacktest",
|
|
281
|
-
"fastquant",
|
|
282
|
-
"lean",
|
|
283
|
-
"ta",
|
|
284
|
-
"finmarketpy",
|
|
285
|
-
"qstrader",
|
|
286
|
-
],
|
|
287
|
-
"server": [
|
|
288
|
-
"fastapi",
|
|
289
|
-
"flask",
|
|
290
|
-
"uvicorn",
|
|
291
|
-
"gunicorn"
|
|
292
|
-
],
|
|
293
|
-
"framework": [
|
|
294
|
-
"lightgbm",
|
|
295
|
-
"catboost",
|
|
296
|
-
"django",
|
|
297
|
-
]
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
installed_packages = {}
|
|
301
|
-
|
|
302
|
-
for category, packages in package_mapping.items():
|
|
303
|
-
installed_packages[category] = []
|
|
304
|
-
for pkg in packages:
|
|
305
|
-
try:
|
|
306
|
-
version = importlib.metadata.version(pkg)
|
|
307
|
-
installed_packages[category].append((pkg, version))
|
|
308
|
-
except importlib.metadata.PackageNotFoundError:
|
|
309
|
-
pass
|
|
310
|
-
|
|
311
|
-
return installed_packages
|
|
320
|
+
from vnai.beam.patching import apply_all_patches
|
|
321
|
+
apply_all_patches()
|
|
322
|
+
_patches_initialized = True
|
|
323
|
+
except Exception:
|
|
324
|
+
_patches_initialized = True
|
|
312
325
|
|
|
313
|
-
def
|
|
314
|
-
|
|
315
|
-
vnstock_initializer.check_terms_accepted()
|
|
326
|
+
def _trigger_patching_after_init():
|
|
327
|
+
_ensure_patches_applied()
|
vnai/beam/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
def __getattr__(name):
|
|
2
|
+
if name =='guardian':
|
|
3
|
+
from vnai.beam.quota import guardian
|
|
4
|
+
return guardian
|
|
5
|
+
elif name =='optimize':
|
|
6
|
+
from vnai.beam.quota import optimize
|
|
7
|
+
return optimize
|
|
8
|
+
elif name =='collector':
|
|
9
|
+
from vnai.beam.metrics import collector
|
|
10
|
+
return collector
|
|
11
|
+
elif name =='capture':
|
|
12
|
+
from vnai.beam.metrics import capture
|
|
13
|
+
return capture
|
|
14
|
+
elif name =='monitor':
|
|
15
|
+
from vnai.beam.pulse import monitor
|
|
16
|
+
return monitor
|
|
17
|
+
elif name =='get_auth_state_manager':
|
|
18
|
+
from vnai.beam.auth import get_auth_state_manager
|
|
19
|
+
return get_auth_state_manager
|
|
20
|
+
elif name =='AuthStateManager':
|
|
21
|
+
from vnai.beam.auth import AuthStateManager
|
|
22
|
+
return AuthStateManager
|
|
23
|
+
elif name =='authenticator':
|
|
24
|
+
from vnai.beam.auth import authenticator
|
|
25
|
+
return authenticator
|
|
26
|
+
raise AttributeError(f"module 'vnai.beam' has no attribute '{name}'")
|