Spaces:
Running
Running
Update crypto_tools.py
Browse files- crypto_tools.py +134 -118
crypto_tools.py
CHANGED
@@ -1,130 +1,146 @@
|
|
1 |
-
|
2 |
-
import requests
|
3 |
-
import pandas as pd
|
4 |
-
import numpy as np
|
5 |
import os
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
response = requests.get(url, params=params, timeout=10)
|
25 |
-
response.raise_for_status()
|
26 |
-
|
27 |
-
data = response.json()
|
28 |
-
|
29 |
-
if crypto_id in data:
|
30 |
-
price = data[crypto_id]['usd']
|
31 |
-
change_24h = data[crypto_id].get('usd_24h_change', 0)
|
32 |
-
return f"${price:,.2f} (24h change: {change_24h:+.2f}%)"
|
33 |
-
else:
|
34 |
-
# Try common alternative names
|
35 |
-
alternatives = {
|
36 |
-
'btc': 'bitcoin',
|
37 |
-
'eth': 'ethereum',
|
38 |
-
'ada': 'cardano',
|
39 |
-
'dot': 'polkadot',
|
40 |
-
'sol': 'solana'
|
41 |
}
|
42 |
|
43 |
-
|
44 |
-
|
45 |
|
46 |
-
|
47 |
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
"
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
'ids': crypto_id,
|
62 |
-
'vs_currencies': 'usd',
|
63 |
-
'include_market_cap': 'true'
|
64 |
-
}
|
65 |
-
|
66 |
-
response = requests.get(url, params=params, timeout=10)
|
67 |
-
response.raise_for_status()
|
68 |
-
|
69 |
-
data = response.json()
|
70 |
-
|
71 |
-
if crypto_id in data:
|
72 |
-
market_cap = data[crypto_id].get('usd_market_cap', 0)
|
73 |
-
return f"${market_cap:,.0f}"
|
74 |
-
else:
|
75 |
-
return f"Market cap data not found for '{crypto_name}'"
|
76 |
-
|
77 |
-
except Exception as e:
|
78 |
-
return f"Error fetching market cap: {str(e)}"
|
79 |
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
signal = "overbought"
|
91 |
-
elif mock_rsi < 30:
|
92 |
-
signal = "oversold"
|
93 |
-
else:
|
94 |
-
signal = "neutral"
|
95 |
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
price_result = get_crypto_price(crypto_name)
|
107 |
-
|
108 |
-
# Extract price from result (simplified approach)
|
109 |
-
if "$" in price_result:
|
110 |
-
try:
|
111 |
-
current_price = float(price_result.split("$")[1].split(" ")[0].replace(",", ""))
|
112 |
-
# Mock 7-day MA (in production, calculate from historical data)
|
113 |
-
import random
|
114 |
-
ma_7 = current_price * random.uniform(0.95, 1.05)
|
115 |
-
return f"7-day MA: ${ma_7:,.2f}"
|
116 |
-
except:
|
117 |
-
return "Unable to calculate moving average"
|
118 |
-
else:
|
119 |
-
return "Unable to get price for moving average calculation"
|
120 |
|
121 |
-
|
122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
|
124 |
-
class
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# crypto_tools.py - CrewAI Native Version
|
|
|
|
|
|
|
2 |
import os
|
3 |
+
import requests
|
4 |
+
from crewai.tools import BaseTool
|
5 |
+
from typing import Type
|
6 |
+
from pydantic import BaseModel, Field
|
7 |
+
|
8 |
+
class CryptoPriceInput(BaseModel):
|
9 |
+
"""Input schema for CryptoPriceTool."""
|
10 |
+
crypto_name: str = Field(..., description="Name of the cryptocurrency to get price for")
|
11 |
|
12 |
+
class CryptoPriceTool(BaseTool):
|
13 |
+
name: str = "Get Crypto Price"
|
14 |
+
description: str = "Gets the current price of a cryptocurrency from CoinGecko API"
|
15 |
+
args_schema: Type[BaseModel] = CryptoPriceInput
|
16 |
+
|
17 |
+
def _run(self, crypto_name: str) -> str:
|
18 |
+
try:
|
19 |
+
crypto_id = crypto_name.lower().replace(' ', '-')
|
20 |
+
|
21 |
+
url = "https://api.coingecko.com/api/v3/simple/price"
|
22 |
+
params = {
|
23 |
+
'ids': crypto_id,
|
24 |
+
'vs_currencies': 'usd',
|
25 |
+
'include_market_cap': 'true',
|
26 |
+
'include_24hr_change': 'true'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
|
29 |
+
response = requests.get(url, params=params, timeout=10)
|
30 |
+
response.raise_for_status()
|
31 |
|
32 |
+
data = response.json()
|
33 |
|
34 |
+
if crypto_id in data:
|
35 |
+
price = data[crypto_id]['usd']
|
36 |
+
change_24h = data[crypto_id].get('usd_24h_change', 0)
|
37 |
+
return f"${price:,.2f} (24h change: {change_24h:+.2f}%)"
|
38 |
+
else:
|
39 |
+
# Try common alternatives
|
40 |
+
alternatives = {
|
41 |
+
'btc': 'bitcoin',
|
42 |
+
'eth': 'ethereum',
|
43 |
+
'ada': 'cardano',
|
44 |
+
'dot': 'polkadot',
|
45 |
+
'sol': 'solana'
|
46 |
+
}
|
47 |
+
|
48 |
+
if crypto_name.lower() in alternatives:
|
49 |
+
return self._run(alternatives[crypto_name.lower()])
|
50 |
+
|
51 |
+
return f"Cryptocurrency '{crypto_name}' not found. Try using full name like 'bitcoin' instead of 'btc'."
|
52 |
+
|
53 |
+
except Exception as e:
|
54 |
+
return f"Error fetching price data: {str(e)}"
|
55 |
|
56 |
+
class MarketCapInput(BaseModel):
|
57 |
+
"""Input schema for MarketCapTool."""
|
58 |
+
crypto_name: str = Field(..., description="Name of the cryptocurrency to get market cap for")
|
59 |
+
|
60 |
+
class MarketCapTool(BaseTool):
|
61 |
+
name: str = "Get Market Cap"
|
62 |
+
description: str = "Gets the market capitalization of a cryptocurrency"
|
63 |
+
args_schema: Type[BaseModel] = MarketCapInput
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
|
65 |
+
def _run(self, crypto_name: str) -> str:
|
66 |
+
try:
|
67 |
+
crypto_id = crypto_name.lower().replace(' ', '-')
|
68 |
+
|
69 |
+
url = "https://api.coingecko.com/api/v3/simple/price"
|
70 |
+
params = {
|
71 |
+
'ids': crypto_id,
|
72 |
+
'vs_currencies': 'usd',
|
73 |
+
'include_market_cap': 'true'
|
74 |
+
}
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
+
response = requests.get(url, params=params, timeout=10)
|
77 |
+
response.raise_for_status()
|
78 |
+
|
79 |
+
data = response.json()
|
80 |
+
|
81 |
+
if crypto_id in data:
|
82 |
+
market_cap = data[crypto_id].get('usd_market_cap', 0)
|
83 |
+
return f"${market_cap:,.0f}"
|
84 |
+
else:
|
85 |
+
return f"Market cap data not found for '{crypto_name}'"
|
86 |
+
|
87 |
+
except Exception as e:
|
88 |
+
return f"Error fetching market cap: {str(e)}"
|
89 |
+
|
90 |
+
class RSIInput(BaseModel):
|
91 |
+
"""Input schema for RSITool."""
|
92 |
+
crypto_name: str = Field(..., description="Name of the cryptocurrency to calculate RSI for")
|
93 |
+
|
94 |
+
class RSITool(BaseTool):
|
95 |
+
name: str = "Calculate RSI"
|
96 |
+
description: str = "Calculates the RSI (Relative Strength Index) for a cryptocurrency"
|
97 |
+
args_schema: Type[BaseModel] = RSIInput
|
98 |
|
99 |
+
def _run(self, crypto_name: str) -> str:
|
100 |
+
try:
|
101 |
+
# Mock RSI for demo (in production, you'd calculate from historical data)
|
102 |
+
import random
|
103 |
+
mock_rsi = round(random.uniform(20, 80), 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
+
if mock_rsi > 70:
|
106 |
+
signal = "overbought"
|
107 |
+
elif mock_rsi < 30:
|
108 |
+
signal = "oversold"
|
109 |
+
else:
|
110 |
+
signal = "neutral"
|
111 |
+
|
112 |
+
return f"RSI: {mock_rsi}, Signal: {signal}"
|
113 |
+
|
114 |
+
except Exception as e:
|
115 |
+
return f"Error calculating RSI: {str(e)}"
|
116 |
+
|
117 |
+
class MovingAverageInput(BaseModel):
|
118 |
+
"""Input schema for MovingAverageTool."""
|
119 |
+
crypto_name: str = Field(..., description="Name of the cryptocurrency to calculate moving average for")
|
120 |
|
121 |
+
class MovingAverageTool(BaseTool):
|
122 |
+
name: str = "Calculate Moving Average"
|
123 |
+
description: str = "Calculates the 7-day moving average for a cryptocurrency"
|
124 |
+
args_schema: Type[BaseModel] = MovingAverageInput
|
125 |
+
|
126 |
+
def _run(self, crypto_name: str) -> str:
|
127 |
+
try:
|
128 |
+
# Get current price first
|
129 |
+
price_tool = CryptoPriceTool()
|
130 |
+
price_result = price_tool._run(crypto_name)
|
131 |
+
|
132 |
+
# Extract price from result
|
133 |
+
if "$" in price_result:
|
134 |
+
try:
|
135 |
+
current_price = float(price_result.split("$")[1].split(" ")[0].replace(",", ""))
|
136 |
+
# Mock 7-day MA
|
137 |
+
import random
|
138 |
+
ma_7 = current_price * random.uniform(0.95, 1.05)
|
139 |
+
return f"7-day MA: ${ma_7:,.2f}"
|
140 |
+
except:
|
141 |
+
return "Unable to calculate moving average"
|
142 |
+
else:
|
143 |
+
return "Unable to get price for moving average calculation"
|
144 |
+
|
145 |
+
except Exception as e:
|
146 |
+
return f"Error calculating moving average: {str(e)}"
|