stock/tests/integration/test_factor_market_integration.py
2026-02-27 03:17:12 +08:00

278 lines
9.8 KiB
Python

"""Integration tests for factor market system.
Tests the complete factor purchase and usage flow.
"""
import pytest
from datetime import datetime
from openclaw.factor import FactorStore
from openclaw.factor.base import BuyFactor, SellFactor
from openclaw.factor.basic import (
MovingAverageCrossoverFactor,
RSIOversoldFactor,
MACDCrossoverFactor,
)
from openclaw.factor.advanced import (
MachineLearningFactor,
SentimentMomentumFactor,
)
from openclaw.core.economy import TradingEconomicTracker
class TestFactorMarketIntegration:
"""Integration tests for factor market."""
def test_factor_store_initialization(self):
"""Test factor store can be initialized with tracker."""
tracker = TradingEconomicTracker(agent_id="test_trader")
store = FactorStore(agent_id="test_trader", tracker=tracker)
assert store.agent_id == "test_trader"
assert store.tracker == tracker
assert len(store.inventory) >= 0
def test_list_available_factors(self):
"""Test listing available factors."""
tracker = TradingEconomicTracker(agent_id="test_trader")
store = FactorStore(agent_id="test_trader", tracker=tracker)
factors = store.list_available()
assert isinstance(factors, list)
assert len(factors) > 0
def test_basic_factors_unlocked_by_default(self):
"""Test basic factors are unlocked by default."""
tracker = TradingEconomicTracker(agent_id="test_trader")
store = FactorStore(agent_id="test_trader", tracker=tracker)
# Basic factors should be available
basic_factor = store.get_factor("buy_ma_crossover")
assert basic_factor is not None
assert basic_factor.metadata.price == 0.0
assert basic_factor.is_unlocked
def test_advanced_factors_locked_by_default(self):
"""Test advanced factors are locked by default."""
tracker = TradingEconomicTracker(agent_id="test_trader")
store = FactorStore(agent_id="test_trader", tracker=tracker)
# Advanced factors should not be usable without purchase
# They exist in catalog but not in inventory
ml_factor = store.catalog.get("buy_ml_prediction")
assert ml_factor is not None
assert not ml_factor.is_unlocked
# Cannot get factor from store without purchasing
assert store.get_factor("buy_ml_prediction") is None
class TestFactorPurchaseFlow:
"""Tests for factor purchase flow."""
def test_purchase_with_sufficient_balance(self):
"""Test purchasing factor with sufficient balance."""
# Create tracker with sufficient capital
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=1000.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
# Try to purchase an advanced factor (SentimentMomentum costs $75)
result = store.purchase("buy_sentiment_momentum")
# Should succeed with sufficient balance
assert result.success is True
assert result.price == 75.0
assert result.new_balance == 925.0
def test_purchase_with_insufficient_balance(self):
"""Test purchasing factor with insufficient balance."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=50.0 # Not enough for ML factor ($100)
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
initial_balance = tracker.balance
# Try to purchase expensive factor
result = store.purchase("buy_ml_prediction")
assert result.success is False
assert "insufficient" in result.message.lower()
assert tracker.balance == initial_balance # Balance unchanged
def test_purchase_deducts_balance(self):
"""Test that purchase deducts balance correctly."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=200.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
initial_balance = tracker.balance
# Purchase a factor (SentimentMomentum costs $75)
result = store.purchase("buy_sentiment_momentum")
assert result.success is True
# Balance should be deducted
assert tracker.balance < initial_balance
assert tracker.balance == initial_balance - 75.0
def test_purchase_already_owned_fails(self):
"""Test that purchasing an already owned factor fails."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=200.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
# Purchase once
result1 = store.purchase("buy_sentiment_momentum")
assert result1.success is True
# Try to purchase again
result2 = store.purchase("buy_sentiment_momentum")
assert result2.success is False
assert "already owned" in result2.message.lower()
def test_factor_unlocked_after_purchase(self):
"""Test that factor is unlocked after purchase."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=200.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
# Before purchase - cannot get factor
assert store.get_factor("buy_sentiment_momentum") is None
# Purchase
result = store.purchase("buy_sentiment_momentum")
assert result.success is True
# After purchase - factor is available
factor = store.get_factor("buy_sentiment_momentum")
assert factor is not None
assert factor.is_unlocked
class TestFactorInventory:
"""Tests for factor inventory management."""
def test_list_owned_factors(self):
"""Test listing owned factors."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=500.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
# Initially should have only free basic factors
owned = store.list_owned()
basic_owned = [f for f in owned if f['price'] == 0.0]
assert len(basic_owned) > 0
# Purchase an advanced factor
store.purchase("buy_sentiment_momentum")
owned = store.list_owned()
advanced_owned = [f for f in owned if f['price'] > 0.0]
assert len(advanced_owned) == 1
assert advanced_owned[0]['id'] == "buy_sentiment_momentum"
def test_get_factor_info(self):
"""Test getting factor information."""
tracker = TradingEconomicTracker(agent_id="test_trader")
store = FactorStore(agent_id="test_trader", tracker=tracker)
info = store.get_factor_info("buy_ml_prediction")
assert info is not None
assert info['name'] == "ML Prediction"
assert info['price'] == 100.0
assert info['category'] == "advanced"
def test_inventory_value(self):
"""Test calculating inventory value."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=500.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
initial_value = store.get_inventory_value()
# Purchase an advanced factor
store.purchase("buy_sentiment_momentum")
new_value = store.get_inventory_value()
assert new_value == initial_value + 75.0
class TestAdvancedFactors:
"""Tests for advanced factor functionality."""
def test_machine_learning_factor_creation(self):
"""Test ML factor can be created."""
factor = MachineLearningFactor()
assert factor.metadata.name == "ML Prediction"
assert factor.metadata.price == 100.0
assert factor.metadata.category.value == "advanced"
def test_sentiment_momentum_factor_creation(self):
"""Test sentiment momentum factor can be created."""
factor = SentimentMomentumFactor()
assert factor.metadata.name == "Sentiment Momentum"
assert factor.metadata.price == 75.0
assert factor.metadata.category.value == "advanced"
def test_multi_factor_combination_creation(self):
"""Test multi-factor combination can be created."""
from openclaw.factor.advanced import MultiFactorCombination
factor = MultiFactorCombination()
assert factor.metadata.name == "Multi-Factor Ensemble"
assert factor.metadata.price == 150.0
assert factor.metadata.category.value == "premium"
def test_purchase_persistence(self):
"""Test purchase history is tracked."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=500.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
# Purchase factors
store.purchase("buy_sentiment_momentum")
store.purchase("buy_ml_prediction")
# Check purchase history
history = store.get_purchase_history()
assert len(history) == 2
assert history[0].factor_id == "buy_sentiment_momentum"
assert history[0].price == 75.0
assert history[1].factor_id == "buy_ml_prediction"
assert history[1].price == 100.0
class TestStoreSummary:
"""Tests for store summary functionality."""
def test_store_summary(self):
"""Test getting store summary."""
tracker = TradingEconomicTracker(
agent_id="test_trader",
initial_capital=500.0
)
store = FactorStore(agent_id="test_trader", tracker=tracker)
summary = store.get_store_summary()
assert summary['agent_id'] == "test_trader"
assert summary['current_balance'] == 500.0
assert 'factors_owned' in summary
assert 'basic' in summary['factors_owned']
assert 'advanced' in summary['factors_owned']