import uuid
from datetime import datetime
from decimal import Decimal
import pytest
from sqlalchemy.orm import Session
from nomy_data_models.models.position import (
MarketType,
Position,
PositionDirection,
PositionStatus,
)
@pytest.fixture
def open_position() -> Position:
position = Position()
position.id = uuid.uuid4()
position.position_id = uuid.uuid4()
position.chain_id = 1
position.market_type = MarketType.SPOT
position.position_direction = PositionDirection.BUY
position.wallet_address = "0x1234567890123456789012345678901234567890"
position.token_symbol_pair = "ETH/USDT"
position.token_address_pair = "0x1234567890123456789012345678901234567890/0x0987654321098765432109876543210987654321"
position.base_token_symbol = "ETH"
position.base_token_address = "0x1234567890123456789012345678901234567890"
position.quote_token_symbol = "USDT"
position.quote_token_address = "0x0987654321098765432109876543210987654321"
position.status = PositionStatus.OPEN
position.current_base_amount = Decimal("1.0")
position.original_base_amount = Decimal("1.0")
position.avg_entry_price = Decimal("1000.0")
position.current_average_entry_price = Decimal("1000.0")
position.avg_exit_price = Decimal("0.0")
position.cost_basis = Decimal("1000.0")
position.leverage = Decimal("1.0")
position.realized_pnl = Decimal("0.0")
position.realized_pnl_usd = Decimal("0.0")
position.opened_at = datetime.now()
position.exchange = "uniswap"
position.trading_fee_symbol = "USDT"
return position
@pytest.fixture
def closed_position() -> Position:
position = Position()
position.id = uuid.uuid4()
position.position_id = uuid.uuid4()
position.chain_id = 1
position.market_type = MarketType.SPOT
position.position_direction = PositionDirection.BUY
position.wallet_address = "0x1234567890123456789012345678901234567890"
position.token_symbol_pair = "ETH/USDT"
position.token_address_pair = "0x1234567890123456789012345678901234567890/0x0987654321098765432109876543210987654321"
position.base_token_symbol = "ETH"
position.base_token_address = "0x1234567890123456789012345678901234567890"
position.quote_token_symbol = "USDT"
position.quote_token_address = "0x0987654321098765432109876543210987654321"
position.status = PositionStatus.CLOSED
position.current_base_amount = Decimal("0.0")
position.original_base_amount = Decimal("1.0")
position.avg_entry_price = Decimal("1000.0")
position.current_average_entry_price = Decimal("1000.0")
position.avg_exit_price = Decimal("0.0")
position.cost_basis = Decimal("1000.0")
position.leverage = Decimal("1.0")
position.realized_pnl = Decimal("100.0")
position.realized_pnl_usd = Decimal("100.0")
position.realized_roi = Decimal("0.1")
position.opened_at = datetime.now()
position.exchange = "uniswap"
return position
class TestPositionStatus:
def test_position_status_values(self) -> None:
assert PositionStatus.OPEN.value == "open", "OPEN value should be 'open'"
assert (
PositionStatus.CLOSED.value == "closed"
), "CLOSED value should be 'closed'"
def test_position_status_comparison(self) -> None:
assert PositionStatus.OPEN == PositionStatus.OPEN, "OPEN should equal itself"
assert (
PositionStatus.OPEN != PositionStatus.CLOSED
), "OPEN should not equal CLOSED"
assert (
PositionStatus.CLOSED == PositionStatus.CLOSED
), "CLOSED should equal itself"
class TestMarketType:
def test_market_type_values(self) -> None:
assert MarketType.SPOT.value == "spot", "SPOT value should be 'spot'"
assert MarketType.PERPETUAL.value == "perp", "PERPETUAL value should be 'perp'"
def test_market_type_comparison(self) -> None:
assert MarketType.SPOT == MarketType.SPOT, "SPOT should equal itself"
assert (
MarketType.SPOT != MarketType.PERPETUAL
), "SPOT should not equal PERPETUAL"
assert (
MarketType.PERPETUAL == MarketType.PERPETUAL
), "PERPETUAL should equal itself"
class TestPositionDirection:
def test_position_direction_values(self) -> None:
assert PositionDirection.BUY.value == "buy", "BUY value should be 'buy'"
assert PositionDirection.SELL.value == "sell", "SELL value should be 'sell'"
def test_position_direction_comparison(self) -> None:
assert PositionDirection.BUY == PositionDirection.BUY, "BUY should equal itself"
assert (
PositionDirection.BUY != PositionDirection.SELL
), "BUY should not equal SELL"
assert (
PositionDirection.SELL == PositionDirection.SELL
), "SELL should equal itself"
class TestPosition:
def test_position_creation(self, open_position: Position) -> None:
assert open_position.id is not None, "ID should be set"
assert open_position.position_id is not None, "Position ID should be set"
assert open_position.chain_id == 1, "Chain ID should be 1"
assert (
open_position.market_type == MarketType.SPOT
), "Position type should be SPOT"
assert (
open_position.position_direction == PositionDirection.BUY
), "Position direction should be BUY"
assert (
open_position.wallet_address == "0x1234567890123456789012345678901234567890"
), "Wallet address should match"
assert (
open_position.token_symbol_pair == "ETH/USDT"
), "Token symbol pair should be 'ETH/USDT'"
assert (
open_position.token_address_pair
== "0x1234567890123456789012345678901234567890/0x0987654321098765432109876543210987654321"
), "Token address pair should match"
assert (
open_position.base_token_symbol == "ETH"
), "Base token symbol should be 'ETH'"
assert (
open_position.base_token_address
== "0x1234567890123456789012345678901234567890"
), "Base token address should match"
assert (
open_position.quote_token_symbol == "USDT"
), "Quote token symbol should be 'USDT'"
assert (
open_position.quote_token_address
== "0x0987654321098765432109876543210987654321"
), "Quote token address should match"
assert open_position.status == PositionStatus.OPEN, "Status should be OPEN"
assert open_position.current_base_amount == Decimal(
"1.0"
), "Current base amount should be 1.0"
assert open_position.original_base_amount == Decimal(
"1.0"
), "Original base amount should be 1.0"
assert open_position.avg_entry_price == Decimal(
"1000.0"
), "Average entry price should be 1000.0"
assert open_position.current_average_entry_price == Decimal(
"1000.0"
), "Current average entry price should be 1000.0"
assert open_position.cost_basis == Decimal(
"1000.0"
), "Cost basis should be 1000.0"
assert open_position.leverage == Decimal("1.0"), "Leverage should be 1.0"
assert open_position.realized_pnl == Decimal(
"0.0"
), "Realized PnL should be 0.0"
assert open_position.realized_pnl_usd == Decimal(
"0.0"
), "Realized PnL USD should be 0.0"
assert open_position.opened_at is not None, "Opened at timestamp should be set"
assert open_position.exchange == "uniswap", "Exchange should be 'uniswap'"
def test_position_with_closed_status(self, closed_position: Position) -> None:
assert closed_position.id is not None, "ID should be set"
assert closed_position.position_id is not None, "Position ID should be set"
assert closed_position.chain_id == 1, "Chain ID should be 1"
assert (
closed_position.market_type == MarketType.SPOT
), "Position type should be SPOT"
assert (
closed_position.position_direction == PositionDirection.BUY
), "Position direction should be BUY"
assert (
closed_position.wallet_address
== "0x1234567890123456789012345678901234567890"
), "Wallet address should match"
assert (
closed_position.token_symbol_pair == "ETH/USDT"
), "Token symbol pair should be 'ETH/USDT'"
assert (
closed_position.token_address_pair
== "0x1234567890123456789012345678901234567890/0x0987654321098765432109876543210987654321"
), "Token address pair should match"
assert (
closed_position.base_token_symbol == "ETH"
), "Base token symbol should be 'ETH'"
assert (
closed_position.base_token_address
== "0x1234567890123456789012345678901234567890"
), "Base token address should match"
assert (
closed_position.quote_token_symbol == "USDT"
), "Quote token symbol should be 'USDT'"
assert (
closed_position.quote_token_address
== "0x0987654321098765432109876543210987654321"
), "Quote token address should match"
assert (
closed_position.status == PositionStatus.CLOSED
), "Status should be CLOSED"
assert closed_position.current_base_amount == Decimal(
"0.0"
), "Current base amount should be 0.0"
assert closed_position.original_base_amount == Decimal(
"1.0"
), "Original base amount should be 1.0"
assert closed_position.avg_entry_price == Decimal(
"1000.0"
), "Average entry price should be 1000.0"
assert closed_position.current_average_entry_price == Decimal(
"1000.0"
), "Current average entry price should be 1000.0"
assert closed_position.cost_basis == Decimal(
"1000.0"
), "Cost basis should be 1000.0"
assert closed_position.leverage == Decimal("1.0"), "Leverage should be 1.0"
assert closed_position.realized_pnl == Decimal(
"100.0"
), "Realized PnL should be 100.0"
assert closed_position.realized_pnl_usd == Decimal(
"100.0"
), "Realized PnL USD should be 100.0"
assert closed_position.realized_roi == Decimal("0.1"), "ROI should be 0.1"
assert (
closed_position.opened_at is not None
), "Opened at timestamp should be set"
assert closed_position.exchange == "uniswap", "Exchange should be 'uniswap'"
def test_position_db_integration(self, session: Session) -> None:
position = Position()
position.position_id = uuid.uuid4()
position.chain_id = 1
position.market_type = MarketType.SPOT
position.position_direction = PositionDirection.BUY
position.wallet_address = "0x1234567890123456789012345678901234567890"
position.token_symbol_pair = "ETH/USDT"
position.token_address_pair = "0x1234567890123456789012345678901234567890/0x0987654321098765432109876543210987654321"
position.base_token_symbol = "ETH"
position.base_token_address = "0x1234567890123456789012345678901234567890"
position.quote_token_symbol = "USDT"
position.quote_token_address = "0x0987654321098765432109876543210987654321"
position.status = PositionStatus.OPEN
position.current_base_amount = Decimal("1.0")
position.original_base_amount = Decimal("1.0")
position.avg_entry_price = Decimal("1000.0")
position.current_average_entry_price = Decimal("1000.0")
position.avg_exit_price = Decimal("0.0")
position.cost_basis = Decimal("1000.0")
position.leverage = Decimal("1.0")
position.realized_pnl = Decimal("0.0")
position.realized_pnl_usd = Decimal("0.0")
position.opened_at = datetime.now()
position.exchange = "uniswap"
session.add(position)
session.commit()
retrieved = session.query(Position).filter_by(id=position.id).first()
assert retrieved is not None, "Position should be retrievable from database"
assert retrieved.id == position.id, "Retrieved position ID should match"
assert (
retrieved.position_id == position.position_id
), "Retrieved position_id should match"
assert (
retrieved.wallet_address == "0x1234567890123456789012345678901234567890"
), "Retrieved wallet address should match"
assert (
retrieved.token_symbol_pair == "ETH/USDT"
), "Retrieved token symbol pair should match"
assert (
retrieved.status == PositionStatus.OPEN
), "Retrieved status should be OPEN"
assert retrieved.current_base_amount == Decimal(
"1.0"
), "Retrieved current base amount should match"
assert retrieved.original_base_amount == Decimal(
"1.0"
), "Retrieved original base amount should match"
assert retrieved.avg_entry_price == Decimal(
"1000.0"
), "Retrieved average entry price should match"
assert retrieved.current_average_entry_price == Decimal(
"1000.0"
), "Retrieved current average entry price should match"
assert retrieved.leverage == Decimal("1.0"), "Retrieved leverage should match"
assert retrieved.trades == [], "Initially, trades list should be empty"
assert retrieved.matches == [], "Initially, matches list should be empty"
if __name__ == "__main__":
pytest.main(["-v", __file__])