매수가능조회_설정값_역할및_코드영향_분석
종목선정 탭 · 매수가능조회 영역 설정값 역할 및 코드 영향 분석
작성 목적: 종목선정 탭의 매수가능조회 영역에 노출된 설정값(탈출가비율, 타임컷, 컷수익, 손절, 갭Low/Mid/High, 본전기준)의 역할·영향을 정리하고, 코드베이스 반영 여부 및 매수·매도 방향 가이드를 제공한다.
대상 UI:
- PC:
irm/frontend/src/App.tsx— 종목선정 탭 내 “매수가능조회” 블록 + 설정 1·2행 - 모바일:
irm/frontend_mobile/src/App.tsx— 동일 설정 항목
1. 설정값 요약 및 DB/API 매핑
| UI 라벨 | DB/API 필드 | 기본값 | 단위 | 비고 |
|---|---|---|---|---|
| 탈출가비율 | exit_percentage |
5.0 | % | 하향 탈출가 = 매수가 × (1 - 값/100) |
| 타임컷(분) | time_cut_minutes |
20 | 분 | 타임컷 적용 경과 시간 |
| 컷수익 | time_cut_profit_min |
1.0 | % | 타임컷 시 “수익 부진” 기준 최소 수익률 |
| 손절 | hard_stop_rate |
-3.0 | % | 하한 수익률 이탈 시 즉시 매도 |
| 갭Low | gap_low |
3.0 | % | 동적 갭: 최고 수익률 0~3% 미만 구간 |
| 갭Mid | gap_mid |
1.5 | % | 동적 갭: 3%~7% 미만 구간 |
| 갭High | gap_high |
1.0 | % | 동적 갭: 7% 이상 구간 |
| 본전기준 | break_even_threshold |
2.0 | % | 본전 보장 적용 최소 수익률 |
- 저장 위치: 사용자·환경별
user_environment_settings(실전/모의 분리), 없으면users테이블 폴백. - API:
GET/PUT /api/v1/user/settings에서 위 필드 조회·저장.
2. 각 설정값의 역할과 영향
2.1 탈출가비율 (exit_percentage)
- 역할: 매수 직후 하향 탈출가를 정하는 비율.
하향 탈출가 = 매수가 × (1 - 탈출가비율/100)
현재가가 이 가격 이하로 내려가면 “하향 탈출”로 매도 대상이 됨. - 추가 동작:
- 가격이 올라가면 “최고가”가 갱신되고, 그 최고가 기준으로 동일 비율로 하향 탈출가가 다시 계산됨(트레일링 형태).
- 상향 탈출가는 별도 설정(목표가)이며, 이 비율과는 무관.
- 매수와의 관계:
매수 시점에 “얼마만큼 떨어지면 손절할지” 리스크 범위를 정하는 값.
비율을 크게 하면 하락 허용 폭이 커지고, 작게 하면 조기 하향 매도에 가깝게 동작.
코드 위치
irm/backend/services/exit_point_manager.py:_get_user_exit_percentage,set_exit_point,update_exit_pointirm/backend/services/exit_point_store.py: 탈출가 계산irm/backend/api/restful/routes.py: 매수 시exit_percentage전달 시 해당 값으로 탈출지점 설정
2.2 타임컷(분) (time_cut_minutes) · 컷수익 (time_cut_profit_min)
역할:
- 타임컷(분): 매수 후 경과 시간(분).
- 컷수익: “이 수익률 미만이면 수익 부진”으로 보는 기준(%).
조건:
경과분 >= 타임컷(분)이고현재 수익률 < 컷수익이면 타임컷 매도 발생.
→ “일정 시간 지났는데 수익이 너무 적으면 매도하고 다른 종목으로 교체”하는 로직.매수와의 관계:
직접적으로 “무엇을 매수할지”를 정하지는 않음.
매수 후 보유 시간과 최소 수익 기대를 정해서, 지루한 종목을 정리하고 재진입/교체 매수로 이어지게 하는 매도·재진입 방향을 잡는 설정.
코드 위치
irm/backend/services/trader.py:check_sell_signal내 Step 1 —elapsed_minutes >= tc_min and current_profit_rate < tc_profit일 때 타임컷 매도 반환.
2.3 손절 (hard_stop_rate)
- 역할: 하한 수익률(%) 이탈 시 즉시 매도.
현재 수익률 <= 손절이면 “손절” 사유로 매도 신호. - 매수와의 관계:
매수 종목 선정에는 관여하지 않음.
다만 재진입 필터에서 “당일 손절/본전(수익률 ≤ 0) 매도한 종목”은 60분 쿨타임 후에만 재진입 가능하므로, 손절로 매도된 종목은 일정 시간 동안 재매수에서 제외되는 간접적 매수(재진입) 영향이 있음.
코드 위치
irm/backend/services/trader.py:check_sell_signalStep 2 —current_profit_rate <= hard_stopirm/backend/services/stock_selection_runner.py: 재진입 필터에서profit_rate_pct <= 0인 경우 60분 쿨타임(손절/본전 동일 취급)
2.4 갭Low · 갭Mid · 갭High (gap_low, gap_mid, gap_high)
역할: 동적 트레일링 스탑용 갭(%).
매수 후 최고 수익률 구간에 따라 허용 하락 폭이 달라짐.최고 수익률 구간 사용 갭 0% ~ 3% 미만 갭Low 3% ~ 7% 미만 갭Mid 7% 이상 갭High 계산:
트레일링 스탑가 = 최고가 × (1 - 갭/100).
현재가가 이 가격 아래로 내려가면 트레일링 스탑 매도.매수와의 관계:
어떤 종목을 매수할지에는 미사용.
“얼마 올랐을 때 얼마만큼만 되돌리면 매도할지”를 정하는 매도 방향 설정.
갭을 크게 하면 되돌림을 더 허용(보유 유지), 작게 하면 조기 익절에 가깝게 동작.
코드 위치
irm/backend/services/trader.py:_get_gap_for_max_profit,check_sell_signalStep 3
2.5 본전기준 (break_even_threshold)
- 역할: 본전 보장 적용 조건.
한 번이라도 최고 수익률이 본전기준 이상이 되었으면, 트레일링 스탑가가 매수가(본전) 아래로 내려가지 않도록 올려서, 본전 이하에서는 매도하지 않음. - 매수와의 관계:
매수 종목 선정에는 미사용.
“일정 수익까지 갔다가 되돌아와도 최소한 본전에서는 팔리게” 하는 매도 방어 설정.
값이 크면 “본전 보장이 걸리기까지 필요한 수익”이 커짐.
코드 위치
irm/backend/services/trader.py:check_sell_signalStep 3 —max_profit_rate >= break_even and calculated_stop_price < buy_price일 때calculated_stop_price = buy_price로 상한
3. 코드베이스 영향 정리
3.1 실제로 설정값을 사용하는 모듈
| 모듈 | 사용 설정 | 용도 |
|---|---|---|
backend/services/exit_point_manager.py |
exit_percentage |
하향 탈출가 계산(설정·갱신), 환경별 조회 |
backend/services/exit_point_store.py |
exit_percentage |
탈출가 저장 시 계산 |
backend/services/trader.py |
time_cut_minutes, time_cut_profit_min, hard_stop_rate, gap_low/mid/high, break_even_threshold |
4단계 매도 신호(타임컷, 손절, 트레일링, 목표가) |
backend/api/restful/routes.py |
전 항목 | GET/PUT /api/v1/user/settings 조회·저장, 매수 시 exit_percentage 전달 반영 |
backend/model/database.py |
전 항목 | User, UserEnvironmentSettings 컬럼 정의 |
frontend/src/App.tsx, frontend_mobile/src/App.tsx |
전 항목 | 매수가능조회 영역 설정 UI 및 저장 요청 |
3.2 모니터링·매도 흐름
- monitor_loop:
ExitPointManager.get_all_exit_points로 탈출지점 조회 → 환경별 현재가 조회 →Trader.check_sell_signal(exit_point, current_price, user_id, user_settings=None)호출. user_settings=None이면Trader._load_user_settings(user_id)로 User 테이블만 조회하여 타임컷·컷수익·손절·갭·본전기준을 적용.
3.3 환경별 설정과의 불일치 가능성
- API:
GET/PUT /api/v1/user/settings는 **현재 백엔드 환경(실전/모의)**에 따라user_environment_settings행이 있으면 해당 행을, 없으면User를 사용. - Trader:
_load_user_settings는 User 테이블만 사용.
→ 실전/모의별로 다른 값을 두고 싶어도, 모니터링(매도 신호)에는 현재 User 테이블 값만 적용됨.
→ 실전/모의별로 탈출·타임컷·손절·갭·본전을 다르게 쓰려면, Trader에서도 환경별UserEnvironmentSettings를 참조하도록 수정이 필요함.
3.4 매수·재진입에만 쓰이는 개념
- 탈출가비율: 매수 API 호출 시 탈출지점 설정에 사용되므로 매수 직후 리스크 범위에 직접 영향.
- 손절/본전: 재진입 필터에서 “당일 손절/본전(수익률 ≤ 0) 매도” 이력이 있으면 60분 쿨타임.
본전기준 수치 자체는 재진입 로직에서 사용하지 않고, “실제 매도 시 수익률이 0 이하인지”만 사용.
4. 매수 방향 가이드 (설정값이 매수·매도에 미치는 영향)
4.1 “매수”에 직접 영향을 주는 설정
- 탈출가비율
- 매수 시점에 “몇 % 떨어지면 하향 탈출할지”를 정함.
- 높이면: 하락 허용 폭이 커져, 변동성 있는 종목을 조금 더 오래 붙들 수 있음.
- 낮추면: 조금만 떨어져도 하향 탈출 → 보수적 매도.
- 매수 “방향”이라기보다, 매수 후 리스크 한도를 정하는 값.
나머지(타임컷, 컷수익, 손절, 갭, 본전기준)는 매수 종목 선정 로직에는 사용되지 않음.
재진입만 “당일 손절/본전 여부 + 쿨타임”으로 제한되므로, 손절로 매도된 종목은 60분 동안 재매수 후보에서 제외된다는 점만 매수(재진입)에 영향을 줌.
4.2 “매도·재진입” 방향을 잡는 설정 (요약)
| 설정 | 값을 키우면 | 값을 줄이면 |
|---|---|---|
| 탈출가비율 | 하향 탈출이 더 넓은 하락에서 발생(보유 연장) | 더 일찍 하향 탈출(보수적) |
| 타임컷(분) | 타임컷 매도가 더 늦게 발생 | 더 빨리 “수익 부진” 정리 |
| 컷수익 | 타임컷이 덜 걸림(낮은 수익도 허용) | 타임컷이 더 잘 걸림(수익 부진 기준 강화) |
| 손절 | 손절선이 더 아래(손실 더 허용) | 손절선이 더 위(일찍 손절) |
| 갭Low/Mid/High | 트레일링 스탑이 느슨해짐(되돌림 더 허용) | 트레일링 스탑이 타이트해짐(일찍 익절) |
| 본전기준 | 본전 보장이 걸리려면 더 높은 수익 필요 | 더 낮은 수익에서도 본전 보장 적용 |
4.3 추천 조합 개념 (참고)
- 공격적: 탈출가비율·갭을 크게, 타임컷(분) 길게, 컷수익 낮게, 손절선 여유 있게 → 보유 연장·재진입 기회 증가.
- 보수적: 탈출가비율·갭 작게, 타임컷 짧게, 컷수익 높게, 손절선 타이트하게 → 일찍 정리·손실 제한.
- 본전 우선: 본전기준을 2% 전후로 두고, 갭은 적당히 → 한 번 올랐다 내려와도 본전 이하 매도는 피함.
5. 설정 변경 시 모니터링 반영 여부 (코드베이스 조사)
질문: 종목 매수 후 모니터링 중에 사용자가 설정값(탈출가비율, 타임컷, 컷수익, 손절, 갭, 본전기준)을 변경하면, 모니터링이 변경된 값을 인지하여 반영하는가?
5.1 결론 요약
| 구분 | 반영 여부 | 조건·비고 |
|---|---|---|
| 타임컷, 컷수익, 손절, 갭Low/Mid/High, 본전기준 | 환경에 따라 다름 | User 테이블에 저장된 경우에만 반영. UserEnvironmentSettings만 갱신된 경우에는 반영 안 됨. |
| 탈출가비율 | 모니터링 루프에서는 미사용 | 현재 모니터링은 Trader.check_sell_signal만 사용하며, 하향 탈출가(exit_price)를 비교하지 않음. 변경해도 진행 중인 모니터링 판단에는 영향 없음. |
5.2 동작 흐름 (코드 기준)
모니터링 루프 (
irm/monitoring/monitor_loop.py)- 매 루프(약 1초 주기)마다
ExitPointManager.get_all_exit_points(uid, environment=None)로 탈출지점 목록 조회. - 각
exit_point마다Trader.check_sell_signal(exit_point, current_price, user_id, user_settings=None)호출. - 항상
user_settings=None으로 호출 → 매번 Trader가 설정을 스스로 로드.
- 매 루프(약 1초 주기)마다
Trader.check_sell_signal (
irm/backend/services/trader.py)if user_settings is None:일 때user_settings = Trader._load_user_settings(user_id)실행.- 즉, 종목마다·루프마다 DB에서 설정을 다시 읽음 (캐시 없음).
Trader._load_user_settings
- User 테이블만 조회함.
UserEnvironmentSettings는 조회하지 않음. - 반환 필드:
time_cut_minutes,time_cut_profit_min,hard_stop_rate,gap_low,gap_mid,gap_high,break_even_threshold.
- User 테이블만 조회함.
PUT /api/v1/user/settings (
irm/backend/api/restful/routes.py)- 현재 환경(실전/모의)에 해당하는
UserEnvironmentSettings행이 있으면 해당 행만 갱신하고 User 테이블은 갱신하지 않음. UserEnvironmentSettings테이블이 없거나 오류 시에만 User 테이블을 갱신하는 폴백 경로 존재.
- 현재 환경(실전/모의)에 해당하는
5.3 시나리오별 정리
UserEnvironmentSettings에만 저장되는 경우 (일반적인 경우)
- UI에서 "설정 저장" 시 실전/모의별로
user_environment_settings행만 갱신. - Trader는 User만 읽으므로 모니터링에는 변경값이 반영되지 않음.
- 같은 프로세스가 계속 도는 한, 모니터링 재시작해도 Trader는 여전히 User만 보므로 반영 안 됨.
- UI에서 "설정 저장" 시 실전/모의별로
User 테이블에 저장되는 경우
user_environment_settings미사용(테이블 없음 등)으로 API가 User만 갱신하는 경로로 저장한 경우.- 다음 루프에서
_load_user_settings가 새 값을 읽으므로 타임컷·컷수익·손절·갭·본전기준 변경이 곧바로 반영됨.
탈출가비율
- 매수 시점에
exit_price가 계산되어 exit_points 테이블에 저장됨. - 모니터링 루프에서는
Trader.check_sell_signal만 호출하며, 이 함수는 exit_point 내 exit_price를 사용하지 않음 (buy_price, highest_price, upper_exit_price만 사용). - 따라서 모니터링 중에 탈출가비율을 바꿔도, 이미 저장된 exit_price는 그대로이며, 현재 루프의 매도 여부 판단에는 반영 경로가 없음.
- (최고가 갱신 시 탈출가를 다시 쓰는
ExitPointManager.update_exit_point는 모니터링 루프에서 호출되지 않음.)
- 매수 시점에
5.4 개선 시 권장 사항
타임컷·컷수익·손절·갭·본전기준이 실전/모의별로 곧바로 반영되려면:
Trader._load_user_settings(user_id)에서 **현재 모니터링 대상 환경(real/virtual)**을 인자로 받고,- 해당 환경에 대한
UserEnvironmentSettings행을 우선 조회한 뒤, 없을 때만 User 테이블을 사용하도록 변경하는 것이 필요함. - 이때 모니터링 루프에서
check_sell_signal호출 시exit_point["environment"]를 전달할 수 있음.
탈출가비율을 모니터링에 반영하려면:
- 매 루프에서 최고가 갱신 시
ExitPointManager.update_exit_point를 호출해, 현재 사용자 설정 비율로 하향 탈출가를 재계산하거나, - 또는
Trader.check_sell_signal내부에서 "현재가 ≤ (최고가 또는 매수가 기준 적용 비율)" 조건을 추가하는 방식이 필요함. - 현재는 Trader가 exit_point의
exit_price를 사용하지 않으므로, 설정 변경이 곧바로 반영되는 경로가 없음.
- 매 루프에서 최고가 갱신 시
6. 참고 파일 목록
irm/backend/model/database.py— User, UserEnvironmentSettings 컬럼irm/backend/services/trader.py— 4단계 매도 신호(타임컷, 손절, 동적 갭+본전, 목표가)irm/backend/services/exit_point_manager.py— 탈출가 비율·설정·갱신irm/backend/api/restful/routes.py— user settings API, 매수 시 exit_percentageirm/monitoring/monitor_loop.py— 탈출지점 모니터링 및 Trader.check_sell_signal 호출irm/backend/services/stock_selection_runner.py— 재진입 필터(손절/본전 60분 쿨)irm/frontend/src/App.tsx,irm/frontend_mobile/src/App.tsx— 매수가능조회 영역 UI