Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

okx trading #93

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/skills/cex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
# CEX Skills Documentation

CEX skills are first-class skills designed for interacting with centralized cryptocurrency exchanges like OKX.

## Using the trade_on_okx Skill

1. Configure your OKX API credentials in the Agent model.
2. Use the `trade_on_okx` skill to automatically trade cryptocurrencies based on technical indicators.
3. Input Parameters:
- `symbol`: The trading pair (e.g., BTC/USDT).
- `timeframe`: The timeframe for the analysis (e.g., 1h).
- `amount`: The amount to trade.

## Example

```python
from skills.cex.okx import TradeOnOkx

trade_skill = TradeOnOkx(api_key, secret, password)
trade_skill.run("BTC/USDT", timeframe="1h", amount=0.001)
```

"""
21 changes: 21 additions & 0 deletions models/agent.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional
from skills.cex.okx import TradeOnOkx

from epyxid import XID
from fastapi import HTTPException
Expand Down Expand Up @@ -657,3 +658,23 @@ def save(self, db: Session) -> None:
db.add(self)

db.commit()

def initialize_agent():
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not here, add cex_config and cex_skills in the model Agent in this file.
like "enso_skills" and enso_config

cex_config = {
"api_key": "your_okx_api_key",
"secret": "your_okx_secret",
"password": "your_okx_password",
}

cex_skills = {
"trade_on_okx": TradeOnOkx(
api_key=cex_config['api_key'],
secret=cex_config['secret'],
password=cex_config['password']
)
}

return {
"cex_skills": cex_skills,
"cex_config": cex_config,
}
13 changes: 13 additions & 0 deletions skills/CEX/_init_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from langchain_core.tools import BaseTool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CEX should be cex, use lowercase in the folder name.

from skills.crestal.search_web3_services import search_web3_services
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unused skill, only keep your new skill.

from skills.crestal.trade_on_okx import TradeOnOkx # Import the new skill

def get_common_skill(name: str) -> BaseTool:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the name, you can also pass in cex_config. Then, in the app/core/engine.py initialize_agent function, imitate enso or Twitter to initialize the skills for this category.

if name == "search_web3_services":
return search_web3_services
elif name == "trade_on_okx": # Add the condition for the new tool
# Replace with actual OKX API credentials
api_key = "your_okx_api_key"
secret = "your_okx_secret"
password = "your_okx_password"
return TradeOnOkx(api_key, secret, password)
22 changes: 22 additions & 0 deletions skills/CEX/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from langchain_core.skills import IntentKitSkill
import ccxt
import pandas as pd

class CEXBaseSkill(IntentKitSkill):
"""
Base class for all CEX (Centralized Exchange) skills. Provides shared infrastructure like the ccxt client.
"""
def __init__(self, api_key: str, secret: str, password: str, exchange: str = "okx"):
self.exchange = ccxt.__dict__[exchange]({
'apiKey': api_key,
'secret': secret,
'password': password,
'enableRateLimit': True,
})

def fetch_historical_data(self, symbol, timeframe, limit=200):
"""Fetch historical OHLCV data."""
ohlcv = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
return df
70 changes: 70 additions & 0 deletions skills/CEX/okx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
rom .base import CEXBaseSkill

class TradeOnOkx(CEXBaseSkill):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_run and _arun is required for a skill.

args_schema is required too, if there is no param, please use an empty pydantic object, for example see twitter/mentions.py

"""
A skill to trade cryptocurrencies on OKX using RSI, CCI, Bollinger Bands, and EMA 200 indicators.
"""
name = "trade_on_okx"
description = "Automatically trade crypto on OKX using technical indicators for decision-making."

def calculate_indicators(self, df):
"""Calculate RSI, CCI, Bollinger Bands, and EMA 200."""
df['rsi'] = self.calculate_rsi(df['close'], period=14)
df['cci'] = self.calculate_cci(df, period=20)
df['ema_200'] = df['close'].ewm(span=200).mean()
df['bollinger_mid'] = df['close'].rolling(window=20).mean()
df['bollinger_std'] = df['close'].rolling(window=20).std()
df['bollinger_upper'] = df['bollinger_mid'] + (df['bollinger_std'] * 2)
df['bollinger_lower'] = df['bollinger_mid'] - (df['bollinger_std'] * 2)
return df

@staticmethod
def calculate_rsi(series, period):
"""Calculate the Relative Strength Index (RSI)."""
delta = series.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
return 100 - (100 / (1 + rs))

@staticmethod
def calculate_cci(df, period):
"""Calculate the Commodity Channel Index (CCI)."""
tp = (df['high'] + df['low'] + df['close']) / 3
ma = tp.rolling(window=period).mean()
md = tp.rolling(window=period).apply(lambda x: np.fabs(x - x.mean()).mean())
cci = (tp - ma) / (0.015 * md)
return cci

def determine_signal(self, df):
"""Determine buy/sell signals based on indicators."""
latest = df.iloc[-1]

if (
latest['rsi'] < 30
and latest['cci'] < -100
and latest['close'] < latest['bollinger_lower']
and latest['close'] > latest['ema_200']
):
return 'buy'

if (
latest['rsi'] > 70
and latest['cci'] > 100
and latest['close'] > latest['bollinger_upper']
and latest['close'] < latest['ema_200']
):
return 'sell'

return 'hold'

def execute_trade(self, symbol, signal, amount):
"""Execute a trade on OKX."""
if signal == 'buy':
order = self.exchange.create_market_buy_order(symbol, amount)
print(f"Buy order executed: {order}")
elif signal == 'sell':
order = self.exchange.create_market_sell_order(symbol, amount)
print(f"Sell order executed: {order}")
else:
print("No trade executed.")