""" 경계값 테스트: profit_rate가 정확히 10%, 30%일 때 매도 조건 검증 """ import pytest from src.signals import evaluate_sell_conditions class TestBoundaryConditions: """매도 조건의 경계값 테스트""" def test_profit_rate_exactly_10_percent_triggers_partial_sell(self): """수익률이 정확히 10%일 때 부분 매도(조건3) 발생""" # Given: 매수가 100, 현재가 110 (정확히 10% 수익) buy_price = 100.0 current_price = 110.0 max_price = 110.0 holding_info = {"partial_sell_done": False} # When result = evaluate_sell_conditions(current_price, buy_price, max_price, holding_info) # Then assert result["status"] == "stop_loss" # 부분 익절은 stop_loss (1시간 주기) assert result["sell_ratio"] == 0.5 assert result["set_partial_sell_done"] is True assert "부분 익절" in result["reasons"][0] def test_profit_rate_exactly_30_percent_in_high_zone(self): """최고 수익률 30% 초과 구간에서 수익률이 정확히 30%로 떨어질 때""" # Given: 최고가 135 (35% 수익), 현재가 130 (30% 수익) buy_price = 100.0 current_price = 130.0 max_price = 135.0 holding_info = {"partial_sell_done": True} # When result = evaluate_sell_conditions(current_price, buy_price, max_price, holding_info) # Then: 수익률이 30% 이하(<= 30)로 하락하여 조건5-2 발동 (stop_loss) assert result["status"] == "stop_loss" assert result["sell_ratio"] == 1.0 assert "수익률 보호(조건5" in result["reasons"][0] # 조건5-2도 매칭 def test_profit_rate_below_30_percent_triggers_sell(self): """최고 수익률 30% 초과 구간에서 수익률이 30% 미만으로 떨어질 때""" # Given: 최고가 135 (35% 수익), 현재가 129.99 (29.99% 수익) buy_price = 100.0 current_price = 129.99 max_price = 135.0 holding_info = {"partial_sell_done": True} # When result = evaluate_sell_conditions(current_price, buy_price, max_price, holding_info) # Then: 조건5-2 발동 (수익률 30% 미만으로 하락) assert result["status"] == "stop_loss" assert result["sell_ratio"] == 1.0 assert "수익률 보호(조건5" in result["reasons"][0] # 조건5-2도 매칭 def test_profit_rate_exactly_10_percent_in_mid_zone(self): """최고 수익률 10~30% 구간에서 수익률이 정확히 10%일 때""" # Given: 최고가 120 (20% 수익), 현재가 110 (10% 수익) buy_price = 100.0 current_price = 110.0 max_price = 120.0 holding_info = {"partial_sell_done": True} # When result = evaluate_sell_conditions(current_price, buy_price, max_price, holding_info) # Then: 수익률이 10% 이하(<= 10)로 하락하여 조건4-2 발동 (stop_loss) assert result["status"] == "stop_loss" assert result["sell_ratio"] == 1.0 assert "수익률 보호(조건4" in result["reasons"][0] # 조건4-2도 매칭 def test_profit_rate_below_10_percent_triggers_sell(self): """최고 수익률 10~30% 구간에서 수익률이 10% 미만으로 떨어질 때""" # Given: 최고가 120 (20% 수익), 현재가 109.99 (9.99% 수익) buy_price = 100.0 current_price = 109.99 max_price = 120.0 holding_info = {"partial_sell_done": True} # When result = evaluate_sell_conditions(current_price, buy_price, max_price, holding_info) # Then: 조건4-2 발동 (수익률 10% 미만으로 하락) assert result["status"] == "stop_loss" assert result["sell_ratio"] == 1.0 assert "수익률 보호(조건4" in result["reasons"][0] # 조건4-2도 매칭 def test_partial_sell_already_done_no_duplicate(self): """부분 매도 이미 완료된 경우 중복 발동 안됨""" # Given: 매수가 100, 현재가 110 (10% 수익), 이미 부분 매도 완료 buy_price = 100.0 current_price = 110.0 max_price = 110.0 holding_info = {"partial_sell_done": True} # When result = evaluate_sell_conditions(current_price, buy_price, max_price, holding_info) # Then: 부분 매도 재발동 안됨 assert result["status"] == "hold" assert result["sell_ratio"] == 0.0 assert result["set_partial_sell_done"] is False if __name__ == "__main__": pytest.main([__file__, "-v"])