praisonaiagents 0.0.22__py3-none-any.whl → 0.0.24__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.
- praisonaiagents/agent/agent.py +22 -33
- praisonaiagents/agents/agents.py +18 -4
- praisonaiagents/tools/__init__.py +165 -2
- praisonaiagents/tools/arxiv_tools.py +292 -0
- praisonaiagents/tools/calculator_tools.py +278 -0
- praisonaiagents/tools/csv_tools.py +266 -0
- praisonaiagents/tools/duckdb_tools.py +268 -0
- praisonaiagents/tools/duckduckgo_tools.py +52 -0
- praisonaiagents/tools/excel_tools.py +310 -0
- praisonaiagents/tools/file_tools.py +274 -0
- praisonaiagents/tools/json_tools.py +515 -0
- praisonaiagents/tools/newspaper_tools.py +354 -0
- praisonaiagents/tools/pandas_tools.py +326 -0
- praisonaiagents/tools/python_tools.py +423 -0
- praisonaiagents/tools/shell_tools.py +278 -0
- praisonaiagents/tools/spider_tools.py +431 -0
- praisonaiagents/tools/test.py +56 -0
- praisonaiagents/tools/tools.py +5 -36
- praisonaiagents/tools/wikipedia_tools.py +272 -0
- praisonaiagents/tools/xml_tools.py +498 -0
- praisonaiagents/tools/yaml_tools.py +417 -0
- praisonaiagents/tools/yfinance_tools.py +213 -0
- {praisonaiagents-0.0.22.dist-info → praisonaiagents-0.0.24.dist-info}/METADATA +1 -1
- praisonaiagents-0.0.24.dist-info/RECORD +42 -0
- praisonaiagents-0.0.22.dist-info/RECORD +0 -24
- {praisonaiagents-0.0.22.dist-info → praisonaiagents-0.0.24.dist-info}/WHEEL +0 -0
- {praisonaiagents-0.0.22.dist-info → praisonaiagents-0.0.24.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,417 @@
|
|
1
|
+
"""Tools for working with YAML files.
|
2
|
+
|
3
|
+
Usage:
|
4
|
+
from praisonaiagents.tools import yaml_tools
|
5
|
+
data = yaml_tools.read_yaml("config.yaml")
|
6
|
+
|
7
|
+
or
|
8
|
+
from praisonaiagents.tools import read_yaml, write_yaml, merge_yaml
|
9
|
+
data = read_yaml("config.yaml")
|
10
|
+
"""
|
11
|
+
|
12
|
+
import logging
|
13
|
+
from typing import List, Dict, Union, Optional, Any
|
14
|
+
from importlib import util
|
15
|
+
import os
|
16
|
+
from copy import deepcopy
|
17
|
+
|
18
|
+
class YAMLTools:
|
19
|
+
"""Tools for working with YAML files."""
|
20
|
+
|
21
|
+
def __init__(self):
|
22
|
+
"""Initialize YAMLTools."""
|
23
|
+
self._check_dependencies()
|
24
|
+
|
25
|
+
def _check_dependencies(self):
|
26
|
+
"""Check if required packages are installed."""
|
27
|
+
missing = []
|
28
|
+
for package, module in [('pyyaml', 'yaml'), ('jsonschema', 'jsonschema')]:
|
29
|
+
if util.find_spec(module) is None:
|
30
|
+
missing.append(package)
|
31
|
+
|
32
|
+
if missing:
|
33
|
+
raise ImportError(
|
34
|
+
f"Required packages not available. Please install: {', '.join(missing)}\n"
|
35
|
+
f"Run: pip install {' '.join(missing)}"
|
36
|
+
)
|
37
|
+
|
38
|
+
def read_yaml(
|
39
|
+
self,
|
40
|
+
filepath: str,
|
41
|
+
safe_load: bool = True,
|
42
|
+
encoding: str = 'utf-8'
|
43
|
+
) -> Optional[Union[Dict[str, Any], List[Any]]]:
|
44
|
+
"""Read a YAML file."""
|
45
|
+
try:
|
46
|
+
if util.find_spec('yaml') is None:
|
47
|
+
error_msg = "pyyaml package is not available. Please install it using: pip install pyyaml"
|
48
|
+
logging.error(error_msg)
|
49
|
+
return None
|
50
|
+
|
51
|
+
# Import yaml only when needed
|
52
|
+
import yaml
|
53
|
+
|
54
|
+
with open(filepath, 'r', encoding=encoding) as f:
|
55
|
+
if safe_load:
|
56
|
+
return yaml.safe_load(f)
|
57
|
+
return yaml.load(f, Loader=yaml.FullLoader)
|
58
|
+
except Exception as e:
|
59
|
+
error_msg = f"Error reading YAML file {filepath}: {str(e)}"
|
60
|
+
logging.error(error_msg)
|
61
|
+
return None
|
62
|
+
|
63
|
+
def write_yaml(
|
64
|
+
self,
|
65
|
+
data: Union[Dict[str, Any], List[Any]],
|
66
|
+
filepath: str,
|
67
|
+
default_flow_style: bool = False,
|
68
|
+
encoding: str = 'utf-8',
|
69
|
+
sort_keys: bool = False,
|
70
|
+
allow_unicode: bool = True
|
71
|
+
) -> bool:
|
72
|
+
"""Write data to YAML file."""
|
73
|
+
try:
|
74
|
+
if util.find_spec('yaml') is None:
|
75
|
+
error_msg = "pyyaml package is not available. Please install it using: pip install pyyaml"
|
76
|
+
logging.error(error_msg)
|
77
|
+
return False
|
78
|
+
|
79
|
+
# Import yaml only when needed
|
80
|
+
import yaml
|
81
|
+
|
82
|
+
with open(filepath, 'w', encoding=encoding) as f:
|
83
|
+
yaml.dump(
|
84
|
+
data,
|
85
|
+
f,
|
86
|
+
default_flow_style=default_flow_style,
|
87
|
+
sort_keys=sort_keys,
|
88
|
+
allow_unicode=allow_unicode
|
89
|
+
)
|
90
|
+
return True
|
91
|
+
except Exception as e:
|
92
|
+
error_msg = f"Error writing YAML file {filepath}: {str(e)}"
|
93
|
+
logging.error(error_msg)
|
94
|
+
return False
|
95
|
+
|
96
|
+
def merge_yaml(
|
97
|
+
self,
|
98
|
+
files: List[str],
|
99
|
+
output_file: Optional[str] = None,
|
100
|
+
strategy: str = 'deep'
|
101
|
+
) -> Union[Dict[str, Any], List[Any], None]:
|
102
|
+
"""Merge multiple YAML files."""
|
103
|
+
try:
|
104
|
+
if util.find_spec('yaml') is None:
|
105
|
+
error_msg = "pyyaml package is not available. Please install it using: pip install pyyaml"
|
106
|
+
logging.error(error_msg)
|
107
|
+
return None
|
108
|
+
|
109
|
+
def deep_merge(source: dict, destination: dict) -> dict:
|
110
|
+
"""Deep merge two dictionaries."""
|
111
|
+
for key, value in source.items():
|
112
|
+
if key in destination:
|
113
|
+
if isinstance(value, dict) and isinstance(destination[key], dict):
|
114
|
+
destination[key] = deep_merge(value, destination[key])
|
115
|
+
elif isinstance(value, list) and isinstance(destination[key], list):
|
116
|
+
destination[key].extend(value)
|
117
|
+
else:
|
118
|
+
destination[key] = value
|
119
|
+
else:
|
120
|
+
destination[key] = value
|
121
|
+
return destination
|
122
|
+
|
123
|
+
result = {}
|
124
|
+
for file in files:
|
125
|
+
data = self.read_yaml(file)
|
126
|
+
if data is None:
|
127
|
+
continue
|
128
|
+
|
129
|
+
if strategy == 'deep':
|
130
|
+
if isinstance(data, dict):
|
131
|
+
result = deep_merge(data, result)
|
132
|
+
elif isinstance(data, list):
|
133
|
+
if not result:
|
134
|
+
result = []
|
135
|
+
result.extend(data)
|
136
|
+
else: # shallow
|
137
|
+
if isinstance(data, dict):
|
138
|
+
result.update(data)
|
139
|
+
elif isinstance(data, list):
|
140
|
+
if not result:
|
141
|
+
result = []
|
142
|
+
result.extend(data)
|
143
|
+
|
144
|
+
if output_file:
|
145
|
+
self.write_yaml(result, output_file)
|
146
|
+
|
147
|
+
return result
|
148
|
+
except Exception as e:
|
149
|
+
error_msg = f"Error merging YAML files: {str(e)}"
|
150
|
+
logging.error(error_msg)
|
151
|
+
return None
|
152
|
+
|
153
|
+
def validate_yaml(
|
154
|
+
self,
|
155
|
+
data: Union[Dict[str, Any], List[Any], str],
|
156
|
+
schema: Dict[str, Any]
|
157
|
+
) -> bool:
|
158
|
+
"""Validate YAML data against a schema."""
|
159
|
+
try:
|
160
|
+
if util.find_spec('jsonschema') is None:
|
161
|
+
error_msg = "jsonschema package is not available. Please install it using: pip install jsonschema"
|
162
|
+
logging.error(error_msg)
|
163
|
+
return False
|
164
|
+
|
165
|
+
# Import jsonschema only when needed
|
166
|
+
from jsonschema import validate, ValidationError
|
167
|
+
|
168
|
+
# Load data if file path
|
169
|
+
if isinstance(data, str):
|
170
|
+
data = self.read_yaml(data)
|
171
|
+
if data is None:
|
172
|
+
return False
|
173
|
+
|
174
|
+
try:
|
175
|
+
validate(instance=data, schema=schema)
|
176
|
+
return True
|
177
|
+
except ValidationError as e:
|
178
|
+
logging.error(f"YAML validation error: {str(e)}")
|
179
|
+
return False
|
180
|
+
except Exception as e:
|
181
|
+
error_msg = f"Error validating YAML: {str(e)}"
|
182
|
+
logging.error(error_msg)
|
183
|
+
return False
|
184
|
+
|
185
|
+
def analyze_yaml(
|
186
|
+
self,
|
187
|
+
data: Union[Dict[str, Any], List[Any], str]
|
188
|
+
) -> Optional[Dict[str, Any]]:
|
189
|
+
"""Analyze YAML data structure."""
|
190
|
+
try:
|
191
|
+
# Load data if file path
|
192
|
+
if isinstance(data, str):
|
193
|
+
data = self.read_yaml(data)
|
194
|
+
if data is None:
|
195
|
+
return None
|
196
|
+
|
197
|
+
def analyze_value(value: Any) -> Dict[str, Any]:
|
198
|
+
"""Analyze a single value."""
|
199
|
+
result = {
|
200
|
+
'type': type(value).__name__,
|
201
|
+
'size': len(value) if hasattr(value, '__len__') else 1
|
202
|
+
}
|
203
|
+
|
204
|
+
if isinstance(value, dict):
|
205
|
+
result['keys'] = list(value.keys())
|
206
|
+
result['nested_types'] = {
|
207
|
+
k: type(v).__name__
|
208
|
+
for k, v in value.items()
|
209
|
+
}
|
210
|
+
elif isinstance(value, list):
|
211
|
+
result['element_types'] = list(set(
|
212
|
+
type(x).__name__ for x in value
|
213
|
+
))
|
214
|
+
|
215
|
+
return result
|
216
|
+
|
217
|
+
result = {
|
218
|
+
'structure': analyze_value(data),
|
219
|
+
'stats': {
|
220
|
+
'total_keys': sum(1 for _ in self._walk_dict(data))
|
221
|
+
if isinstance(data, dict) else len(data)
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
return result
|
226
|
+
except Exception as e:
|
227
|
+
error_msg = f"Error analyzing YAML: {str(e)}"
|
228
|
+
logging.error(error_msg)
|
229
|
+
return None
|
230
|
+
|
231
|
+
def _walk_dict(self, d: Dict[str, Any]) -> Any:
|
232
|
+
"""Walk through nested dictionary."""
|
233
|
+
for k, v in d.items():
|
234
|
+
yield k
|
235
|
+
if isinstance(v, dict):
|
236
|
+
yield from self._walk_dict(v)
|
237
|
+
|
238
|
+
def transform_yaml(
|
239
|
+
self,
|
240
|
+
data: Union[Dict[str, Any], List[Any], str],
|
241
|
+
operations: List[Dict[str, Any]]
|
242
|
+
) -> Optional[Union[Dict[str, Any], List[Any]]]:
|
243
|
+
"""Transform YAML data using specified operations."""
|
244
|
+
try:
|
245
|
+
# Load data if file path
|
246
|
+
if isinstance(data, str):
|
247
|
+
data = self.read_yaml(data)
|
248
|
+
if data is None:
|
249
|
+
return None
|
250
|
+
|
251
|
+
result = deepcopy(data)
|
252
|
+
|
253
|
+
for op in operations:
|
254
|
+
op_type = op.get('type')
|
255
|
+
path = op.get('path', '')
|
256
|
+
value = op.get('value')
|
257
|
+
|
258
|
+
if not op_type:
|
259
|
+
continue
|
260
|
+
|
261
|
+
# Split path into parts
|
262
|
+
parts = [p for p in path.split('/') if p]
|
263
|
+
|
264
|
+
# Get reference to target location
|
265
|
+
target = result
|
266
|
+
parent = None
|
267
|
+
last_key = None
|
268
|
+
|
269
|
+
for part in parts[:-1]:
|
270
|
+
if isinstance(target, dict):
|
271
|
+
if part not in target:
|
272
|
+
target[part] = {}
|
273
|
+
parent = target
|
274
|
+
target = target[part]
|
275
|
+
last_key = part
|
276
|
+
elif isinstance(target, list):
|
277
|
+
idx = int(part)
|
278
|
+
while len(target) <= idx:
|
279
|
+
target.append({})
|
280
|
+
parent = target
|
281
|
+
target = target[idx]
|
282
|
+
last_key = idx
|
283
|
+
|
284
|
+
if parts:
|
285
|
+
last_part = parts[-1]
|
286
|
+
if isinstance(target, dict):
|
287
|
+
if op_type == 'set':
|
288
|
+
target[last_part] = value
|
289
|
+
elif op_type == 'delete':
|
290
|
+
target.pop(last_part, None)
|
291
|
+
elif op_type == 'append' and isinstance(target.get(last_part), list):
|
292
|
+
target[last_part].append(value)
|
293
|
+
elif isinstance(target, list):
|
294
|
+
idx = int(last_part)
|
295
|
+
if op_type == 'set':
|
296
|
+
while len(target) <= idx:
|
297
|
+
target.append(None)
|
298
|
+
target[idx] = value
|
299
|
+
elif op_type == 'delete' and idx < len(target):
|
300
|
+
del target[idx]
|
301
|
+
elif op_type == 'append':
|
302
|
+
target.append(value)
|
303
|
+
else:
|
304
|
+
if op_type == 'set':
|
305
|
+
result = value
|
306
|
+
elif op_type == 'append' and isinstance(result, list):
|
307
|
+
result.append(value)
|
308
|
+
|
309
|
+
return result
|
310
|
+
except Exception as e:
|
311
|
+
error_msg = f"Error transforming YAML: {str(e)}"
|
312
|
+
logging.error(error_msg)
|
313
|
+
return None
|
314
|
+
|
315
|
+
# Create instance for direct function access
|
316
|
+
_yaml_tools = YAMLTools()
|
317
|
+
read_yaml = _yaml_tools.read_yaml
|
318
|
+
write_yaml = _yaml_tools.write_yaml
|
319
|
+
merge_yaml = _yaml_tools.merge_yaml
|
320
|
+
validate_yaml = _yaml_tools.validate_yaml
|
321
|
+
analyze_yaml = _yaml_tools.analyze_yaml
|
322
|
+
transform_yaml = _yaml_tools.transform_yaml
|
323
|
+
|
324
|
+
if __name__ == "__main__":
|
325
|
+
# Example usage
|
326
|
+
print("\n==================================================")
|
327
|
+
print("YAMLTools Demonstration")
|
328
|
+
print("==================================================\n")
|
329
|
+
|
330
|
+
# Sample data
|
331
|
+
data1 = {
|
332
|
+
'server': {
|
333
|
+
'host': 'localhost',
|
334
|
+
'port': 8080,
|
335
|
+
'debug': True
|
336
|
+
},
|
337
|
+
'database': {
|
338
|
+
'url': 'postgresql://localhost:5432/db',
|
339
|
+
'pool_size': 5
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
data2 = {
|
344
|
+
'server': {
|
345
|
+
'workers': 4,
|
346
|
+
'timeout': 30
|
347
|
+
},
|
348
|
+
'logging': {
|
349
|
+
'level': 'INFO',
|
350
|
+
'file': 'app.log'
|
351
|
+
}
|
352
|
+
}
|
353
|
+
|
354
|
+
# 1. Write YAML files
|
355
|
+
print("1. Writing YAML Files")
|
356
|
+
print("------------------------------")
|
357
|
+
success1 = write_yaml(data1, 'config1.yaml')
|
358
|
+
success2 = write_yaml(data2, 'config2.yaml')
|
359
|
+
print(f"First file written: {success1}")
|
360
|
+
print(f"Second file written: {success2}")
|
361
|
+
print()
|
362
|
+
|
363
|
+
# 2. Read YAML file
|
364
|
+
print("2. Reading YAML File")
|
365
|
+
print("------------------------------")
|
366
|
+
config = read_yaml('config1.yaml')
|
367
|
+
print("YAML content:")
|
368
|
+
print(config)
|
369
|
+
print()
|
370
|
+
|
371
|
+
# 3. Merge YAML files
|
372
|
+
print("3. Merging YAML Files")
|
373
|
+
print("------------------------------")
|
374
|
+
merged = merge_yaml(['config1.yaml', 'config2.yaml'])
|
375
|
+
print("Merged content:")
|
376
|
+
print(merged)
|
377
|
+
print()
|
378
|
+
|
379
|
+
# 4. Analyze YAML
|
380
|
+
print("4. Analyzing YAML")
|
381
|
+
print("------------------------------")
|
382
|
+
analysis = analyze_yaml(merged)
|
383
|
+
print("Analysis results:")
|
384
|
+
print(analysis)
|
385
|
+
print()
|
386
|
+
|
387
|
+
# 5. Transform YAML
|
388
|
+
print("5. Transforming YAML")
|
389
|
+
print("------------------------------")
|
390
|
+
operations = [
|
391
|
+
{
|
392
|
+
'type': 'set',
|
393
|
+
'path': 'server/host',
|
394
|
+
'value': '0.0.0.0'
|
395
|
+
},
|
396
|
+
{
|
397
|
+
'type': 'delete',
|
398
|
+
'path': 'server/debug'
|
399
|
+
},
|
400
|
+
{
|
401
|
+
'type': 'set',
|
402
|
+
'path': 'logging/handlers',
|
403
|
+
'value': ['console', 'file']
|
404
|
+
}
|
405
|
+
]
|
406
|
+
transformed = transform_yaml(merged, operations)
|
407
|
+
print("Transformed content:")
|
408
|
+
print(transformed)
|
409
|
+
|
410
|
+
print("\n==================================================")
|
411
|
+
print("Demonstration Complete")
|
412
|
+
print("==================================================")
|
413
|
+
|
414
|
+
# Cleanup
|
415
|
+
for file in ['config1.yaml', 'config2.yaml']:
|
416
|
+
if os.path.exists(file):
|
417
|
+
os.remove(file)
|
@@ -0,0 +1,213 @@
|
|
1
|
+
"""YFinance tools for stock market data.
|
2
|
+
|
3
|
+
Usage:
|
4
|
+
from praisonaiagents.tools import get_stock_price, get_stock_info
|
5
|
+
price = get_stock_price("AAPL")
|
6
|
+
info = get_stock_info("AAPL")
|
7
|
+
|
8
|
+
or
|
9
|
+
from praisonaiagents.tools import yfinance
|
10
|
+
price = yfinance.get_stock_price("AAPL")
|
11
|
+
info = yfinance.get_stock_info("AAPL")
|
12
|
+
"""
|
13
|
+
|
14
|
+
from typing import List, Dict, Optional, Any
|
15
|
+
import logging
|
16
|
+
from importlib import util
|
17
|
+
from datetime import datetime
|
18
|
+
|
19
|
+
class YFinanceTools:
|
20
|
+
"""A comprehensive tool for financial data analysis using yfinance"""
|
21
|
+
|
22
|
+
def __init__(self):
|
23
|
+
"""Initialize YFinanceTools"""
|
24
|
+
self._tickers = {}
|
25
|
+
|
26
|
+
def _get_yfinance(self):
|
27
|
+
"""Get yfinance module, installing if needed"""
|
28
|
+
if util.find_spec('yfinance') is None:
|
29
|
+
error_msg = "yfinance package is not available. Please install it using: pip install yfinance"
|
30
|
+
logging.error(error_msg)
|
31
|
+
return None
|
32
|
+
import yfinance as yf
|
33
|
+
return yf
|
34
|
+
|
35
|
+
def _get_ticker(self, symbol: str):
|
36
|
+
"""Get or create ticker instance"""
|
37
|
+
if symbol not in self._tickers:
|
38
|
+
yf = self._get_yfinance()
|
39
|
+
if yf is None:
|
40
|
+
return None
|
41
|
+
self._tickers[symbol] = yf.Ticker(symbol)
|
42
|
+
return self._tickers[symbol]
|
43
|
+
|
44
|
+
def get_stock_price(self, symbol: str) -> Dict[str, float]:
|
45
|
+
"""
|
46
|
+
Get current stock price and related price metrics
|
47
|
+
|
48
|
+
Args:
|
49
|
+
symbol (str): Stock ticker symbol
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
Dict[str, float]: Current price information
|
53
|
+
"""
|
54
|
+
try:
|
55
|
+
ticker = self._get_ticker(symbol)
|
56
|
+
if ticker is None:
|
57
|
+
return {"error": "yfinance package not available"}
|
58
|
+
|
59
|
+
info = ticker.info
|
60
|
+
return {
|
61
|
+
'symbol': symbol,
|
62
|
+
'price': info.get('regularMarketPrice', 0.0),
|
63
|
+
'open': info.get('regularMarketOpen', 0.0),
|
64
|
+
'high': info.get('regularMarketDayHigh', 0.0),
|
65
|
+
'low': info.get('regularMarketDayLow', 0.0),
|
66
|
+
'volume': info.get('regularMarketVolume', 0),
|
67
|
+
'previous_close': info.get('regularMarketPreviousClose', 0.0),
|
68
|
+
'change': info.get('regularMarketChange', 0.0),
|
69
|
+
'change_percent': info.get('regularMarketChangePercent', 0.0)
|
70
|
+
}
|
71
|
+
except Exception as e:
|
72
|
+
error_msg = f"Error getting stock price for {symbol}: {str(e)}"
|
73
|
+
logging.error(error_msg)
|
74
|
+
return {"error": error_msg}
|
75
|
+
|
76
|
+
def get_stock_info(self, symbol: str) -> Dict:
|
77
|
+
"""
|
78
|
+
Get detailed information about a stock
|
79
|
+
|
80
|
+
Args:
|
81
|
+
symbol (str): Stock ticker symbol
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
Dict: Stock information including company details and key metrics
|
85
|
+
"""
|
86
|
+
try:
|
87
|
+
ticker = self._get_ticker(symbol)
|
88
|
+
if ticker is None:
|
89
|
+
return {"error": "yfinance package not available"}
|
90
|
+
|
91
|
+
info = ticker.info
|
92
|
+
|
93
|
+
relevant_info = {
|
94
|
+
"longName": info.get("longName"),
|
95
|
+
"symbol": info.get("symbol"),
|
96
|
+
"sector": info.get("sector"),
|
97
|
+
"industry": info.get("industry"),
|
98
|
+
"country": info.get("country"),
|
99
|
+
"marketCap": info.get("marketCap"),
|
100
|
+
"currentPrice": info.get("currentPrice"),
|
101
|
+
"currency": info.get("currency"),
|
102
|
+
"exchange": info.get("exchange"),
|
103
|
+
"fiftyTwoWeekHigh": info.get("fiftyTwoWeekHigh"),
|
104
|
+
"fiftyTwoWeekLow": info.get("fiftyTwoWeekLow"),
|
105
|
+
"trailingPE": info.get("trailingPE"),
|
106
|
+
"forwardPE": info.get("forwardPE"),
|
107
|
+
"dividendYield": info.get("dividendYield"),
|
108
|
+
"beta": info.get("beta"),
|
109
|
+
"volume": info.get("volume"),
|
110
|
+
"averageVolume": info.get("averageVolume"),
|
111
|
+
"sharesOutstanding": info.get("sharesOutstanding"),
|
112
|
+
"website": info.get("website"),
|
113
|
+
"longBusinessSummary": info.get("longBusinessSummary")
|
114
|
+
}
|
115
|
+
return {k: v for k, v in relevant_info.items() if v is not None}
|
116
|
+
except Exception as e:
|
117
|
+
error_msg = f"Error fetching stock info: {str(e)}"
|
118
|
+
logging.error(error_msg)
|
119
|
+
return {"error": error_msg}
|
120
|
+
|
121
|
+
def get_historical_data(
|
122
|
+
self,
|
123
|
+
symbol: str,
|
124
|
+
period: str = "1y",
|
125
|
+
interval: str = "1d",
|
126
|
+
start: Optional[datetime] = None,
|
127
|
+
end: Optional[datetime] = None
|
128
|
+
) -> List[Dict[str, Any]]:
|
129
|
+
"""
|
130
|
+
Get historical price data for a stock
|
131
|
+
|
132
|
+
Args:
|
133
|
+
symbol (str): Stock ticker symbol
|
134
|
+
period (str): Data period e.g. 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max
|
135
|
+
interval (str): Data interval e.g. 1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo
|
136
|
+
start (datetime, optional): Start date for data
|
137
|
+
end (datetime, optional): End date for data
|
138
|
+
|
139
|
+
Returns:
|
140
|
+
List[Dict[str, Any]]: List of historical price data points
|
141
|
+
"""
|
142
|
+
try:
|
143
|
+
ticker = self._get_ticker(symbol)
|
144
|
+
if ticker is None:
|
145
|
+
return [{"error": "yfinance package not available"}]
|
146
|
+
|
147
|
+
hist = ticker.history(period=period, interval=interval, start=start, end=end)
|
148
|
+
return hist.reset_index().to_dict('records')
|
149
|
+
except Exception as e:
|
150
|
+
error_msg = f"Error fetching historical data: {str(e)}"
|
151
|
+
logging.error(error_msg)
|
152
|
+
return [{"error": error_msg}]
|
153
|
+
|
154
|
+
if __name__ == "__main__":
|
155
|
+
# Example usage
|
156
|
+
print("\n==================================================")
|
157
|
+
print("YFinanceTools Demonstration")
|
158
|
+
print("==================================================\n")
|
159
|
+
|
160
|
+
try:
|
161
|
+
yf_tools = YFinanceTools()
|
162
|
+
|
163
|
+
# 1. Basic Stock Information
|
164
|
+
print("1. Basic Stock Information for AAPL")
|
165
|
+
print("------------------------------")
|
166
|
+
info = yf_tools.get_stock_info("AAPL")
|
167
|
+
if "error" not in info:
|
168
|
+
print(f"Company: {info.get('longName')}")
|
169
|
+
print(f"Sector: {info.get('sector')}")
|
170
|
+
print(f"Industry: {info.get('industry')}")
|
171
|
+
print(f"Country: {info.get('country')}\n")
|
172
|
+
else:
|
173
|
+
print(f"Error: {info['error']}\n")
|
174
|
+
|
175
|
+
# 2. Current Price Data
|
176
|
+
print("2. Current Price Data")
|
177
|
+
print("------------------------------")
|
178
|
+
price_data = yf_tools.get_stock_price("AAPL")
|
179
|
+
if "error" not in price_data:
|
180
|
+
print(f"Current Price: ${price_data.get('price', 'N/A')}")
|
181
|
+
print(f"Previous Close: ${price_data.get('previous_close', 'N/A')}")
|
182
|
+
print(f"Day Range: ${price_data.get('low', 'N/A')} - ${price_data.get('high', 'N/A')}\n")
|
183
|
+
else:
|
184
|
+
print(f"Error: {price_data['error']}\n")
|
185
|
+
|
186
|
+
# 3. Historical Data
|
187
|
+
print("3. Historical Data (Last 5 Days)")
|
188
|
+
print("------------------------------")
|
189
|
+
hist_data = yf_tools.get_historical_data("AAPL", period="5d")
|
190
|
+
if not any("error" in d for d in hist_data):
|
191
|
+
for day in hist_data:
|
192
|
+
print(f"Date: {day.get('Date')}, Close: ${day.get('Close', 'N/A'):.2f}")
|
193
|
+
print()
|
194
|
+
else:
|
195
|
+
print(f"{hist_data[0]['error']}\n")
|
196
|
+
|
197
|
+
# 4. Multi-Stock Example
|
198
|
+
print("5. Multi-Stock Current Prices")
|
199
|
+
print("------------------------------")
|
200
|
+
for symbol in ["AAPL", "MSFT", "GOOGL"]:
|
201
|
+
price_data = yf_tools.get_stock_price(symbol)
|
202
|
+
if "error" not in price_data:
|
203
|
+
print(f"{symbol}: ${price_data.get('price', 'N/A')}")
|
204
|
+
else:
|
205
|
+
print(f"{symbol}: Error fetching price")
|
206
|
+
print()
|
207
|
+
|
208
|
+
except Exception as e:
|
209
|
+
print(f"Error: {str(e)}")
|
210
|
+
|
211
|
+
print("==================================================")
|
212
|
+
print("Analysis Complete")
|
213
|
+
print("==================================================")
|
@@ -0,0 +1,42 @@
|
|
1
|
+
praisonaiagents/__init__.py,sha256=xJLN8i6V9SRmJFMxSRWDQt_hBePoupVd3WanNIgbBbc,1052
|
2
|
+
praisonaiagents/main.py,sha256=7Phfe0gdxHzbhPb3WRzBTfq9CaLq0K31M5DM_4oCiCQ,12451
|
3
|
+
praisonaiagents/agent/__init__.py,sha256=sKO8wGEXvtCrvV1e834r1Okv0XAqAxqZCqz6hKLiTvA,79
|
4
|
+
praisonaiagents/agent/agent.py,sha256=3Y8-eaebjOEculRgiz5IobAf5oadBKEpvNWJE5qaa4A,32305
|
5
|
+
praisonaiagents/agents/__init__.py,sha256=7RDeQNSqZg5uBjD4M_0p_F6YgfWuDuxPFydPU50kDYc,120
|
6
|
+
praisonaiagents/agents/agents.py,sha256=BikzgqE469uUg3OeiBBihpYzuK1RUvRaB_CTc3DPdOM,23589
|
7
|
+
praisonaiagents/build/lib/praisonaiagents/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
|
8
|
+
praisonaiagents/build/lib/praisonaiagents/main.py,sha256=zDhN5KKtKbfruolDNxlyJkcFlkSt4KQkQTDRfQVAhxc,3960
|
9
|
+
praisonaiagents/build/lib/praisonaiagents/agent/__init__.py,sha256=sKO8wGEXvtCrvV1e834r1Okv0XAqAxqZCqz6hKLiTvA,79
|
10
|
+
praisonaiagents/build/lib/praisonaiagents/agent/agent.py,sha256=PwbeW6v4Ldcl10JQr9_7TBfg4_FskQh-mGoFUdGxg8w,15483
|
11
|
+
praisonaiagents/build/lib/praisonaiagents/agents/__init__.py,sha256=cgCLFLFcLp9SizmFSHUkH5aX-1seAAsRtQbtIHBBso4,101
|
12
|
+
praisonaiagents/build/lib/praisonaiagents/agents/agents.py,sha256=P2FAtlfD3kPib5a1oLVYanxlU6e4-GhBMQ0YDY5MHY4,13473
|
13
|
+
praisonaiagents/build/lib/praisonaiagents/task/__init__.py,sha256=VL5hXVmyGjINb34AalxpBMl-YW9m5EDcRkMTKkSSl7c,80
|
14
|
+
praisonaiagents/build/lib/praisonaiagents/task/task.py,sha256=4Y1qX8OeEFcid2yhAiPYylvHpuDmWORsyNL16_BiVvI,1831
|
15
|
+
praisonaiagents/process/__init__.py,sha256=lkYbL7Hn5a0ldvJtkdH23vfIIZLIcanK-65C0MwaorY,52
|
16
|
+
praisonaiagents/process/process.py,sha256=4qXdrCDQPH5MtvHvdJVURXKNgSl6ae3OYTiqAF_A2ZU,24295
|
17
|
+
praisonaiagents/task/__init__.py,sha256=VL5hXVmyGjINb34AalxpBMl-YW9m5EDcRkMTKkSSl7c,80
|
18
|
+
praisonaiagents/task/task.py,sha256=UiiWgLDOdX_w0opP8h8-u-leVZlq1CkpGUmf7L2qyJs,3110
|
19
|
+
praisonaiagents/tools/__init__.py,sha256=bFCnpM_MOiYASz7Y7b0WnFjF68QEgToR3JJgfiAWgfA,7012
|
20
|
+
praisonaiagents/tools/arxiv_tools.py,sha256=1stb31zTjLTon4jCnpZG5de9rKc9QWgC0leLegvPXWo,10528
|
21
|
+
praisonaiagents/tools/calculator_tools.py,sha256=S1xPT74Geurvjm52QMMIG29zDXVEWJmM6nmyY7yF298,9571
|
22
|
+
praisonaiagents/tools/csv_tools.py,sha256=gX2nYz4ktmpKvXB36jx5-GqddntEQD4G2fVQWTIKrwU,8435
|
23
|
+
praisonaiagents/tools/duckdb_tools.py,sha256=KB3b-1HcX7ocoxskDpk_7RRpTGHnH8hizIY0ZdLRbIE,8816
|
24
|
+
praisonaiagents/tools/duckduckgo_tools.py,sha256=LUliFagYtVz7kcgsJfHOC5fbF4RsrT3kFcXoW_4RUr4,1622
|
25
|
+
praisonaiagents/tools/excel_tools.py,sha256=e2HqcwnyBueOyss0xEKxff3zB4w4sNWCOMXvZfbDYlE,11309
|
26
|
+
praisonaiagents/tools/file_tools.py,sha256=KRskI9q8up3sHaLQSaIGtvpl1brq419Up6YvB9QzSoI,8807
|
27
|
+
praisonaiagents/tools/json_tools.py,sha256=ApUYNuQ1qnbmYNCxSlx6Tth_H1yo8mhWtZ7Rr2WS6C4,16507
|
28
|
+
praisonaiagents/tools/newspaper_tools.py,sha256=NyhojNPeyULBGcAWGOT1X70qVkh3FgZrpH-S7PEmrwI,12667
|
29
|
+
praisonaiagents/tools/pandas_tools.py,sha256=_0LxuAtqgIk4OAd1obMY8gg2BHlYLpSXcgfWEOxlPzs,10939
|
30
|
+
praisonaiagents/tools/python_tools.py,sha256=ByBpESi5Vk2ivpihav9AQeqf95K_D4qqINYN1q-q0bA,13428
|
31
|
+
praisonaiagents/tools/shell_tools.py,sha256=P3fSrfOw71CGcrPwdPOA9Fr6Bgt_CAC71bUjCyvZCN8,9301
|
32
|
+
praisonaiagents/tools/spider_tools.py,sha256=lrZnT1V1BC46We-AzBrDB1Ryifr3KKGmYNntMsScU7w,15094
|
33
|
+
praisonaiagents/tools/test.py,sha256=UHOTNrnMo0_H6I2g48re1WNZkrR7f6z25UnlWxiOSbM,1600
|
34
|
+
praisonaiagents/tools/tools.py,sha256=xkZ_8vbT3bcc_H9IxwpC5dmHdu5uBRaYfrd-XEXC78I,264
|
35
|
+
praisonaiagents/tools/wikipedia_tools.py,sha256=vKYvnJlLnG5Ysvhdi5fq8efDMWInfDCXaizYB5WJo9Q,9435
|
36
|
+
praisonaiagents/tools/xml_tools.py,sha256=iYTMBEk5l3L3ryQ1fkUnNVYK-Nnua2Kx2S0dxNMMs1A,17122
|
37
|
+
praisonaiagents/tools/yaml_tools.py,sha256=uogAZrhXV9O7xvspAtcTfpKSQYL2nlOTvCQXN94-G9A,14215
|
38
|
+
praisonaiagents/tools/yfinance_tools.py,sha256=nmzjS7G_5GqMQD4r867mt17dHg5xvtsYDDfOPh68SgE,8105
|
39
|
+
praisonaiagents-0.0.24.dist-info/METADATA,sha256=tGVL_aXSZR0aqaZtnaHL4N_HDAEoJYU7iwj_c5ein3U,233
|
40
|
+
praisonaiagents-0.0.24.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
|
41
|
+
praisonaiagents-0.0.24.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
|
42
|
+
praisonaiagents-0.0.24.dist-info/RECORD,,
|