praisonaiagents 0.0.23__py3-none-any.whl → 0.0.25__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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.23.dist-info → praisonaiagents-0.0.25.dist-info}/METADATA +1 -1
- praisonaiagents-0.0.25.dist-info/RECORD +42 -0
- praisonaiagents-0.0.23.dist-info/RECORD +0 -24
- {praisonaiagents-0.0.23.dist-info → praisonaiagents-0.0.25.dist-info}/WHEEL +0 -0
- {praisonaiagents-0.0.23.dist-info → praisonaiagents-0.0.25.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=TK5njOmDSpMlyBnbeBzNSlnzXWlnNaTpVqkFPhkMArg,265
|
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.25.dist-info/METADATA,sha256=Z5VIr56RrpyJ7xF6mav54_GzlQwmjNMKKj9-4JKeBoY,233
|
40
|
+
praisonaiagents-0.0.25.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
|
41
|
+
praisonaiagents-0.0.25.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
|
42
|
+
praisonaiagents-0.0.25.dist-info/RECORD,,
|