Skip to content

Commit

Permalink
Merge pull request #95 from rhettre/feature/alphasquared
Browse files Browse the repository at this point in the history
Implemented AlphaSquared Trading
  • Loading branch information
rhettre authored Oct 13, 2024
2 parents b31ee2a + 76618d0 commit 8a39a25
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 2 deletions.
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,62 @@ new_schedule = [
client.update_fgi_schedule(new_schedule)
```

## AlphaSquared Integration

This client now includes integration with AlphaSquared, allowing you to execute trading strategies based on AlphaSquared's risk analysis.

### Setup

1. Obtain your AlphaSquared API key from [AlphaSquared](https://alphasquared.io/).

2. Initialize the AlphaSquared client along with the Coinbase client:

```python
from coinbase_advanced_trader import EnhancedRESTClient, AlphaSquaredTrader
from alphasquared import AlphaSquared

# Initialize Coinbase client
coinbase_api_key = "YOUR_COINBASE_API_KEY"

coinbase_api_secret = "YOUR_COINBASE_API_SECRET"

coinbase_client = EnhancedRESTClient(api_key=coinbase_api_key, api_secret=coinbase_api_secret)

# Initialize AlphaSquared client
alphasquared_api_key = "YOUR_ALPHASQUARED_API_KEY"

alphasquared_client = AlphaSquared(alphasquared_api_key, cache_ttl=60)

# Create AlphaSquaredTrader
trader = AlphaSquaredTrader(coinbase_client, alphasquared_client)
```

### Executing AlphaSquared Strategies

To execute a trading strategy based on AlphaSquared's risk analysis:

```python
# Set trading parameters
product_id = "BTC-USDC"

# Your custom strategy name from AlphaSquared
strategy_name = "My Custom Strategy"

# Execute strategy
trader.execute_strategy(product_id, strategy_name)
```

This will:
1. Fetch the current risk level for the specified asset from AlphaSquared.
2. Determine the appropriate action (buy/sell) and value based on the custom strategy defined in AlphaSquared and the current risk.
3. Execute the appropriate trade on Coinbase if the conditions are met.

> **Note:** Make sure to handle exceptions and implement proper logging in your production code. This integration only works with custom strategies; it does not work with the default strategies provided by AlphaSquared.
### Customizing Strategies

You can create custom strategies by modifying the `execute_strategy` method in the `AlphaSquaredTrader` class. This allows you to define specific trading logic based on the risk levels provided by AlphaSquared.

## Legacy Support

The legacy authentication method is still supported but moved to a separate module. It will not receive the latest updates from the Coinbase SDK. To use the legacy method:
Expand Down
4 changes: 4 additions & 0 deletions coinbase_advanced_trader/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .enhanced_rest_client import EnhancedRESTClient
from .alphasquared_trader import AlphaSquaredTrader

__all__ = ['EnhancedRESTClient', 'AlphaSquaredTrader']
75 changes: 75 additions & 0 deletions coinbase_advanced_trader/alphasquared_trader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from decimal import Decimal, ROUND_DOWN
import logging
from .enhanced_rest_client import EnhancedRESTClient
from alphasquared import AlphaSquared
from coinbase_advanced_trader.models import Order

logger = logging.getLogger(__name__)

class AlphaSquaredTrader:
def __init__(self, coinbase_client: EnhancedRESTClient, alphasquared_client: AlphaSquared):
self.coinbase_client = coinbase_client
self.alphasquared_client = alphasquared_client

def execute_strategy(self, product_id: str, strategy_name: str):
try:
asset, base_currency = product_id.split('-')

current_risk = self.alphasquared_client.get_current_risk(asset)
logger.info(f"Current {asset} Risk: {current_risk}")

action, value = self.alphasquared_client.get_strategy_value_for_risk(strategy_name, current_risk)
logger.info(f"Strategy suggests: Action = {action.upper()}, Value = {value}")

if value <= 0:
logger.info("No action taken based on current risk and strategy.")
return

if action.lower() == 'buy':
self._execute_buy(product_id, value)
elif action.lower() == 'sell':
self._execute_sell(product_id, asset, base_currency, value)
else:
logger.info(f"Unknown action: {action}. No trade executed.")

except Exception as e:
logger.error(f"Error in execute_strategy: {str(e)}")
logger.exception("Full traceback:")

def _execute_buy(self, product_id: str, value: float):
try:
order = self.coinbase_client.fiat_limit_buy(product_id, str(value), price_multiplier="0.995")
if isinstance(order, Order):
logger.info(f"Buy limit order placed: ID={order.id}, Size={order.size}, Price={order.price}")
else:
logger.warning(f"Unexpected order response type: {type(order)}")
except Exception as e:
logger.error(f"Error placing buy order: {str(e)}")
logger.exception("Full traceback:")

def _execute_sell(self, product_id, asset, base_currency, value):
balance = Decimal(self.coinbase_client.get_crypto_balance(asset))
logger.info(f"Current {asset} balance: {balance}")

product_details = self.coinbase_client.get_product(product_id)
base_increment = Decimal(product_details['base_increment'])
quote_increment = Decimal(product_details['quote_increment'])
current_price = Decimal(product_details['price'])
logger.info(f"Current {asset} price: {current_price} {base_currency}")

sell_amount = (balance * Decimal(value) / Decimal('100')).quantize(base_increment, rounding=ROUND_DOWN)
logger.info(f"Sell amount: {sell_amount} {asset}")

if sell_amount > base_increment:
limit_price = (current_price * Decimal('1.005')).quantize(quote_increment, rounding=ROUND_DOWN)

order = self.coinbase_client.limit_order_gtc_sell(
client_order_id=self.coinbase_client._order_service._generate_client_order_id(),
product_id=product_id,
base_size=str(sell_amount),
limit_price=str(limit_price)
)

logger.info(f"Sell limit order placed for {sell_amount} {asset} at {limit_price} {base_currency}: {order}")
else:
logger.info(f"Sell amount {sell_amount} {asset} is too small. Minimum allowed is {base_increment}. No order placed.")
63 changes: 63 additions & 0 deletions coinbase_advanced_trader/tests/test_alphasquared_trader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import unittest
from unittest.mock import Mock, patch
from decimal import Decimal
from coinbase_advanced_trader.alphasquared_trader import AlphaSquaredTrader
from coinbase_advanced_trader.models import Order, OrderSide, OrderType

class TestAlphaSquaredTrader(unittest.TestCase):
def setUp(self):
self.mock_coinbase_client = Mock()
self.mock_alphasquared_client = Mock()
self.trader = AlphaSquaredTrader(self.mock_coinbase_client, self.mock_alphasquared_client)

def test_execute_strategy_buy(self):
self.mock_alphasquared_client.get_current_risk.return_value = 30
self.mock_alphasquared_client.get_strategy_value_for_risk.return_value = ('buy', 100)

mock_order = Order(
id='123',
product_id='BTC-USDC',
side=OrderSide.BUY,
type=OrderType.LIMIT,
size=Decimal('0.001'),
price=Decimal('50000')
)
self.mock_coinbase_client.fiat_limit_buy.return_value = mock_order

self.trader.execute_strategy('BTC-USDC', 'TestStrategy')

self.mock_alphasquared_client.get_current_risk.assert_called_once_with('BTC')
self.mock_alphasquared_client.get_strategy_value_for_risk.assert_called_once_with('TestStrategy', 30)
self.mock_coinbase_client.fiat_limit_buy.assert_called_once_with('BTC-USDC', '100', price_multiplier='0.995')

def test_execute_strategy_sell(self):
self.mock_alphasquared_client.get_current_risk.return_value = 70
self.mock_alphasquared_client.get_strategy_value_for_risk.return_value = ('sell', 50)

self.mock_coinbase_client.get_crypto_balance.return_value = '1.0'
self.mock_coinbase_client.get_product.return_value = {
'base_increment': '0.00000001',
'quote_increment': '0.01',
'price': '50000'
}

mock_order = Order(
id='456',
product_id='BTC-USDC',
side=OrderSide.SELL,
type=OrderType.LIMIT,
size=Decimal('0.5'),
price=Decimal('50250')
)
self.mock_coinbase_client.limit_order_gtc_sell.return_value = mock_order

self.trader.execute_strategy('BTC-USDC', 'TestStrategy')

self.mock_alphasquared_client.get_current_risk.assert_called_once_with('BTC')
self.mock_alphasquared_client.get_strategy_value_for_risk.assert_called_once_with('TestStrategy', 70)
self.mock_coinbase_client.get_crypto_balance.assert_called_once_with('BTC')
self.mock_coinbase_client.get_product.assert_called_once_with('BTC-USDC')
self.mock_coinbase_client.limit_order_gtc_sell.assert_called_once()

if __name__ == '__main__':
unittest.main()
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ requests >=2.31.0
urllib3 >= 2.2.2
PyYAML >= 6.0.1
cryptography>=42.0.4
cffi
cffi
alphasquared-py>=0.3.0
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name='coinbase-advancedtrade-python',
version='0.2.5',
version='0.3.0',
description='The unofficial Python client for the Coinbase Advanced Trade API',
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down

0 comments on commit 8a39a25

Please sign in to comment.