menikev commited on
Commit
b43f281
·
verified ·
1 Parent(s): 165f4bd

Update crypto_tools.py

Browse files
Files changed (1) hide show
  1. crypto_tools.py +134 -118
crypto_tools.py CHANGED
@@ -1,130 +1,146 @@
1
- from langchain.tools import tool
2
- import requests
3
- import pandas as pd
4
- import numpy as np
5
  import os
6
- from typing import Dict, Any
 
 
 
 
 
 
 
7
 
8
- # Define tools as standalone functions, not methods
9
- @tool("Get Crypto Price")
10
- def get_crypto_price(crypto_name: str) -> str:
11
- """Gets the current price of a cryptocurrency."""
12
- try:
13
- # Convert crypto name to CoinGecko ID format
14
- crypto_id = crypto_name.lower().replace(' ', '-')
15
-
16
- url = "https://api.coingecko.com/api/v3/simple/price"
17
- params = {
18
- 'ids': crypto_id,
19
- 'vs_currencies': 'usd',
20
- 'include_market_cap': 'true',
21
- 'include_24hr_change': 'true'
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
- if crypto_name.lower() in alternatives:
44
- return get_crypto_price(alternatives[crypto_name.lower()])
45
 
46
- return f"Cryptocurrency '{crypto_name}' not found. Try using full name like 'bitcoin' instead of 'btc'."
47
 
48
- except requests.exceptions.RequestException as e:
49
- return f"Error fetching price data: {str(e)}"
50
- except Exception as e:
51
- return f"Unexpected error: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- @tool("Get Market Cap")
54
- def get_market_cap(crypto_name: str) -> str:
55
- """Gets the market capitalization of a cryptocurrency."""
56
- try:
57
- crypto_id = crypto_name.lower().replace(' ', '-')
58
-
59
- url = "https://api.coingecko.com/api/v3/simple/price"
60
- params = {
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
- @tool("Calculate RSI")
81
- def calculate_rsi(crypto_name: str) -> str:
82
- """Calculates the RSI (Relative Strength Index) for a cryptocurrency."""
83
- try:
84
- # For demo purposes, we'll return a mock RSI
85
- # In production, you'd fetch historical price data and calculate actual RSI
86
- import random
87
- mock_rsi = round(random.uniform(20, 80), 2)
88
-
89
- if mock_rsi > 70:
90
- signal = "overbought"
91
- elif mock_rsi < 30:
92
- signal = "oversold"
93
- else:
94
- signal = "neutral"
95
 
96
- return f"RSI: {mock_rsi}, Signal: {signal}"
97
-
98
- except Exception as e:
99
- return f"Error calculating RSI: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
- @tool("Calculate Moving Average")
102
- def calculate_moving_average(crypto_name: str) -> str:
103
- """Calculates the 7-day moving average for a cryptocurrency."""
104
- try:
105
- # Get current price first
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
- except Exception as e:
122
- return f"Error calculating moving average: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- class CryptoTools:
125
- """Container class for crypto tools - for backward compatibility"""
126
- def __init__(self):
127
- self.get_crypto_price = get_crypto_price
128
- self.get_market_cap = get_market_cap
129
- self.calculate_rsi = calculate_rsi
130
- self.calculate_moving_average = calculate_moving_average
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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)}"