252 lines
7.4 KiB
Python
252 lines
7.4 KiB
Python
"""
|
|
Tests for paper trading functionality.
|
|
"""
|
|
import pytest
|
|
from paper_strategy_instance import PaperStrategyInstance
|
|
from brokers import OrderSide, OrderType, OrderStatus
|
|
|
|
|
|
class TestPaperStrategyInstance:
|
|
"""Tests for PaperStrategyInstance."""
|
|
|
|
def test_create_instance(self):
|
|
"""Test creating a paper strategy instance."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-instance-1',
|
|
strategy_id='test-strategy-1',
|
|
strategy_name='Test Strategy',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
initial_balance=10000.0,
|
|
)
|
|
|
|
assert instance.strategy_instance_id == 'test-instance-1'
|
|
assert instance.starting_balance == 10000.0
|
|
assert instance.get_current_balance() == 10000.0
|
|
assert instance.get_available_balance() == 10000.0
|
|
|
|
def test_update_prices(self):
|
|
"""Test updating prices in paper broker."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-1',
|
|
strategy_id='strat-1',
|
|
strategy_name='Test',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
)
|
|
|
|
instance.update_prices({'BTC/USDT': 50000.0, 'ETH/USDT': 3000.0})
|
|
|
|
assert instance.get_current_price(symbol='BTC/USDT') == 50000.0
|
|
assert instance.get_current_price(symbol='ETH/USDT') == 3000.0
|
|
|
|
def test_trade_order_market_buy(self):
|
|
"""Test placing a market buy order."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-1',
|
|
strategy_id='strat-1',
|
|
strategy_name='Test',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
initial_balance=10000.0,
|
|
commission=0.001,
|
|
)
|
|
|
|
# Set price
|
|
instance.update_prices({'BTC/USDT': 50000.0})
|
|
|
|
# Place order
|
|
result = instance.trade_order(
|
|
trade_type='buy',
|
|
size=0.1,
|
|
order_type='MARKET',
|
|
source={'symbol': 'BTC/USDT'}
|
|
)
|
|
|
|
assert result.success
|
|
assert result.status == OrderStatus.FILLED
|
|
|
|
# Check position exists
|
|
pos = instance.get_position('BTC/USDT')
|
|
assert pos is not None
|
|
assert pos.size == 0.1
|
|
|
|
# Check balance reduced
|
|
assert instance.get_available_balance() < 10000.0
|
|
|
|
def test_trade_order_sell(self):
|
|
"""Test selling a position."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-1',
|
|
strategy_id='strat-1',
|
|
strategy_name='Test',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
initial_balance=10000.0,
|
|
commission=0,
|
|
slippage=0,
|
|
)
|
|
|
|
# Buy first
|
|
instance.update_prices({'BTC/USDT': 50000.0})
|
|
instance.trade_order(
|
|
trade_type='buy',
|
|
size=0.1,
|
|
order_type='MARKET',
|
|
source={'symbol': 'BTC/USDT'}
|
|
)
|
|
|
|
# Now sell at higher price
|
|
instance.update_prices({'BTC/USDT': 51000.0})
|
|
result = instance.trade_order(
|
|
trade_type='sell',
|
|
size=0.1,
|
|
order_type='MARKET',
|
|
source={'symbol': 'BTC/USDT'}
|
|
)
|
|
|
|
assert result.success
|
|
|
|
# Position should be closed
|
|
pos = instance.get_position('BTC/USDT')
|
|
assert pos is None
|
|
|
|
def test_close_position(self):
|
|
"""Test closing a position via close_position method."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-1',
|
|
strategy_id='strat-1',
|
|
strategy_name='Test',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
)
|
|
|
|
instance.update_prices({'BTC/USDT': 50000.0})
|
|
instance.trade_order(
|
|
trade_type='buy',
|
|
size=0.1,
|
|
order_type='MARKET',
|
|
source={'symbol': 'BTC/USDT'}
|
|
)
|
|
|
|
result = instance.close_position('BTC/USDT')
|
|
assert result.success
|
|
|
|
def test_close_all_positions(self):
|
|
"""Test closing all positions."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-1',
|
|
strategy_id='strat-1',
|
|
strategy_name='Test',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
)
|
|
|
|
instance.update_prices({'BTC/USDT': 50000.0, 'ETH/USDT': 3000.0})
|
|
|
|
instance.trade_order(
|
|
trade_type='buy',
|
|
size=0.1,
|
|
order_type='MARKET',
|
|
source={'symbol': 'BTC/USDT'}
|
|
)
|
|
instance.trade_order(
|
|
trade_type='buy',
|
|
size=1.0,
|
|
order_type='MARKET',
|
|
source={'symbol': 'ETH/USDT'}
|
|
)
|
|
|
|
assert instance.get_active_trades() == 2
|
|
|
|
results = instance.close_all_positions()
|
|
assert len(results) == 2
|
|
assert all(r.success for r in results)
|
|
assert instance.get_active_trades() == 0
|
|
|
|
def test_reset(self):
|
|
"""Test resetting paper trading state."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-1',
|
|
strategy_id='strat-1',
|
|
strategy_name='Test',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
initial_balance=10000.0,
|
|
)
|
|
|
|
instance.update_prices({'BTC/USDT': 50000.0})
|
|
instance.trade_order(
|
|
trade_type='buy',
|
|
size=0.1,
|
|
order_type='MARKET',
|
|
source={'symbol': 'BTC/USDT'}
|
|
)
|
|
|
|
assert instance.get_available_balance() < 10000.0
|
|
|
|
instance.reset()
|
|
|
|
assert instance.get_available_balance() == 10000.0
|
|
assert instance.get_active_trades() == 0
|
|
|
|
def test_get_trade_history(self):
|
|
"""Test getting trade history."""
|
|
instance = PaperStrategyInstance(
|
|
strategy_instance_id='test-1',
|
|
strategy_id='strat-1',
|
|
strategy_name='Test',
|
|
user_id=1,
|
|
generated_code='def next(self): pass',
|
|
data_cache=None,
|
|
indicators=None,
|
|
trades=None,
|
|
)
|
|
|
|
instance.update_prices({'BTC/USDT': 50000.0})
|
|
instance.trade_order(
|
|
trade_type='buy',
|
|
size=0.1,
|
|
order_type='MARKET',
|
|
source={'symbol': 'BTC/USDT'}
|
|
)
|
|
|
|
history = instance.get_trade_history()
|
|
assert len(history) == 1
|
|
assert history[0]['symbol'] == 'BTC/USDT'
|
|
assert history[0]['side'] == 'buy'
|
|
|
|
|
|
class TestStrategiesModeSeletion:
|
|
"""Tests for strategy mode selection."""
|
|
|
|
def test_mode_selection_imports(self):
|
|
"""Test that mode selection imports work."""
|
|
from Strategies import Strategies
|
|
from brokers import TradingMode
|
|
|
|
assert TradingMode.PAPER == 'paper'
|
|
assert TradingMode.BACKTEST == 'backtest'
|
|
assert TradingMode.LIVE == 'live'
|