Spaces:
Running
Running
Update confirm_sell_backtest.py
Browse files- confirm_sell_backtest.py +104 -23
confirm_sell_backtest.py
CHANGED
|
@@ -31,22 +31,92 @@ if sys.platform == 'win32':
|
|
| 31 |
# [๋๋ฆด ์ข
๋ชฉ โ ์ํ๋ ๋๋ก]
|
| 32 |
# =============================================
|
| 33 |
TICKERS = {
|
| 34 |
-
'KOSPI': [
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
'
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
],
|
| 51 |
}
|
| 52 |
|
|
@@ -69,19 +139,22 @@ TREND_MIN_DAYS = 60 # '240์ฌ': ์ต๊ทผ N๊ฑฐ๋์ผ ์ฐ์ 240์ ์
|
|
| 69 |
TREND_MIN_GAP = 0.05 # '240์ฌ': ๋งค๋์ผ ์ข
๊ฐ๊ฐ 240์ +5% ์ด์
|
| 70 |
|
| 71 |
# --- ๋งค๋ ์๋ ์ต์ ํํฐ (์์ฒญ์ฌํญ) ---
|
| 72 |
-
SKIP_IF_BELOW_240 = True # ๋งค๋ ์์
|
|
|
|
|
|
|
|
|
|
| 73 |
SKIP_IF_NO_240 = True # 240์ ์ด ์์ผ๋ฉด(๋ฐ์ดํฐ ๋ถ์กฑ) ์๋ ๋
|
| 74 |
MAX_EARLY_DAYS = 129 # ๋งค๋ ํ ์ด ์ผ์๊น์ง๋ง ์ ํจ. ์ด๋ณด๋ค ๋ฆ๊ฒ(130์ผ+) 240์ดํํ๋ฉด
|
| 75 |
# = ๋๋ฌด ์ผ์ฐ ํ ๊ฒ -> ์๋ ๋. (None์ด๋ฉด ์ด ํํฐ ๋)
|
| 76 |
SKIP_IF_STILL_UP = True # ๋งค๋ ํ ๊ด์ฐฐ๊ธฐ๊ฐ ๋ด๋ด 240 ์ ๊นจ๊ณ ์ถ์ธ์ ์ง=ํ๋งค๋(false alarm) -> ์๋ ๋
|
| 77 |
|
| 78 |
-
ANALYZE_FROM = '
|
| 79 |
ANALYZE_TO = None # None=์ค๋
|
| 80 |
|
| 81 |
# โ
๋ฐ์ดํฐ ๋ก๋ฉ์ ANALYZE_FROM ๊ณผ ๋ฌด๊ดํ๊ฒ 'ํญ์ ์ถฉ๋ถํ ๊ณผ๊ฑฐ๋ถํฐ' ๋ถ๋ฌ์จ๋ค.
|
| 82 |
# (๊ณ ์ /์ด๊ฒฉ์ ์ ์ฒด ๊ฐ๊ฒฉ์ด๋ ฅ์ผ๋ก ๊ณ์ฐ๋ผ์ผ ํ๋ฏ๋ก. ANALYZE_FROM ๋ง ๋ฆ์ถ๋ฉด ๊ณ ์ ์
|
| 83 |
# ์๋ชป ์ก์ ๋งค๋์์ ์ด ๋ฌ๋ผ์ง๋ ๋ฒ๊ทธ๊ฐ ์๊น -> ๊ทธ๋์ DATA_START ๋ ๊ณ ์ .)
|
| 84 |
-
DATA_START = '
|
| 85 |
|
| 86 |
|
| 87 |
def _end_date():
|
|
@@ -255,8 +328,11 @@ def classify_240(stock, low, ma240, i, price):
|
|
| 255 |
m = ma240[i]
|
| 256 |
if np.isnan(m):
|
| 257 |
return ('UNKNOWN', None)
|
| 258 |
-
if low[i] <= m: # ์ฅ์ค ์ ๊ฐ๊ฐ 240์ ํฐ์น/์ดํ
|
| 259 |
-
|
|
|
|
|
|
|
|
|
|
| 260 |
end = min(i + 1 + LOOK_AHEAD, len(stock))
|
| 261 |
for k in range(i + 1, end):
|
| 262 |
if not np.isnan(ma240[k]) and low[k] <= ma240[k]:
|
|
@@ -363,9 +439,14 @@ def main():
|
|
| 363 |
# cat == 'PENDING' -> ์ต๊ทผ ์ ํธ๋ผ ํ์ ๋ถ๊ฐ -> ์ ๋ ๋์ง ์์(์๋ ์ด๋ฆผ)
|
| 364 |
isP = bool(protected(stock, i, price))
|
| 365 |
is_run = in_240_run(stock, ma240, i)
|
| 366 |
-
if cat == '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 367 |
down_n += 1
|
| 368 |
-
where = '
|
| 369 |
elif cat == 'EARLY':
|
| 370 |
b = run if is_run else edge
|
| 371 |
b['n'] += 1; b['E'] += 1
|
|
|
|
| 31 |
# [๋๋ฆด ์ข
๋ชฉ โ ์ํ๋ ๋๋ก]
|
| 32 |
# =============================================
|
| 33 |
TICKERS = {
|
| 34 |
+
# 'KOSPI': [
|
| 35 |
+
# '005930', '000660', '373220', '207940', '005380',
|
| 36 |
+
# '000270', '068270', '035420', '035720', '005490',
|
| 37 |
+
# '105560', '055550', '012330', '051910', '006400',
|
| 38 |
+
# '028260', '066570', '096770', '034730', '015760',
|
| 39 |
+
# '204320',
|
| 40 |
+
# '012450',
|
| 41 |
+
# '009150',
|
| 42 |
+
# '011790',
|
| 43 |
+
# ],
|
| 44 |
+
# 'KOSDAQ': [
|
| 45 |
+
# '247540', '086520', '196170', '028300', '348370',
|
| 46 |
+
# '058470', '068760', '263750', '035900', '277810',
|
| 47 |
+
# '041510', '035760', '112040', '293490', '145020',
|
| 48 |
+
# '039030', '240810', '357780', '403870', '121600',
|
| 49 |
+
# '399720',
|
| 50 |
+
# '088130',
|
| 51 |
+
# ],
|
| 52 |
+
'KOSPI' : [
|
| 53 |
+
# '483650', # ๋ฌ๋ฐ๊ธ๋ก๋ฒ
|
| 54 |
+
# '096770', # SK์ด๋
ธ๋ฒ ์ด์
|
| 55 |
+
# '090430', # ์๋ชจ๋ ํผ์ํฝ
|
| 56 |
+
# '326030', # SK๋ฐ์ด์คํ
|
| 57 |
+
# '035420', # NAVER
|
| 58 |
+
# '352820', # ํ์ด๋ธ
|
| 59 |
+
# '003490', # ๋ํํญ๊ณต
|
| 60 |
+
# '025540', # ํ๊ตญ๋จ์
|
| 61 |
+
# '373220', # LG์๋์ง์๋ฃจ์
|
| 62 |
+
# '443060', # HDํ๋๋ง๋ฆฐ์๋ฃจ์
|
| 63 |
+
# '032350', # ๋กฏ๋ฐ๊ด๊ด๊ฐ๋ฐ
|
| 64 |
+
# '005380', # ํ๋์ฐจ
|
| 65 |
+
# '003670', # ํฌ์ค์ฝํจ์ฒ์
|
| 66 |
+
# '011790', # SKC
|
| 67 |
+
# '005930', # ์ผ์ฑ์ ์
|
| 68 |
+
# '000660', # SKํ์ด๋์ค
|
| 69 |
+
],
|
| 70 |
+
'KOSDAQ' : [
|
| 71 |
+
# '078520', # ์์ด๋ธ์จ์์จ
|
| 72 |
+
# '206640', # ๋ฐ๋ํ
๋ฉ๋
|
| 73 |
+
# '302440', # SK๋ฐ์ด์ค์ฌ์ด์ธ์ค
|
| 74 |
+
# '328130', # ๋ฃจ๋
|
| 75 |
+
# '005250', # ๋
น์ญ์ํ๋ฉ์ค
|
| 76 |
+
# '234690', # ๋
น์ญ์์ฐ๋น
|
| 77 |
+
# '083930', # ์๋ฐ์ฝ
|
| 78 |
+
# '195940', # HK์ด๋
ธ์
|
| 79 |
+
# '122870', # ์์ด์ง์ํฐํ
์ธ๋จผํธ
|
| 80 |
+
# '112610', # ์จ์์ค์๋
|
| 81 |
+
# '257720', # ์ค๋ฆฌ์ฝํฌ
|
| 82 |
+
# '086710', # ์ ์ง๋ทฐํฐ์ฌ์ด์ธ์ค
|
| 83 |
+
# '217730', # ๊ฐ์คํ
๋ฐ์ด์คํ
|
| 84 |
+
# '003570', # SNT๋ค์ด๋ด๋ฏน์ค
|
| 85 |
+
# '194370', # ์ ์ด์์ค์ฝํผ๋ ์ด์
|
| 86 |
+
# '131030', # ์ตํฌ์ค์ ์ฝ
|
| 87 |
+
# '204320', # HL๋ง๋
|
| 88 |
+
# '096530', # ์จ์
|
| 89 |
+
# '035900', # JYP Ent.
|
| 90 |
+
# '178920', # PI์ฒจ๋จ์์ฌ
|
| 91 |
+
# '216080', # ์ ํ
๋ง
|
| 92 |
+
# '099320', # ์ํธ๋ ์์ด
|
| 93 |
+
# '088130', # ๋์์ํ
|
| 94 |
+
# '420770', # ๊ธฐ๊ฐ๋น์ค
|
| 95 |
+
# '222080', # SFA๋ฐ๋์ฒด
|
| 96 |
+
# '147830', # ์ ๋ฃก์ฐ์
|
| 97 |
+
# '281820', # ์ผ์ด์จํ
|
| 98 |
+
# '017510', # ์ธ๋ช
์ ๊ธฐ
|
| 99 |
+
# '112290', # ์์ด์จ์ผ
|
| 100 |
+
# '089010', # ์ผํธ๋ก๋์ค
|
| 101 |
+
# '102120', # ์ด๋ณด๋ธ๋ฐ๋์ฒด
|
| 102 |
+
# '251370', # ์์ด์์ด์นํฐ
|
| 103 |
+
# '094360', # ์นฉ์ค์ค๋ฏธ๋์ด
|
| 104 |
+
# '166090', # ํ๋๋จธํฐ๋ฆฌ์ผ์ฆ
|
| 105 |
+
# '277810', # ๋ ์ธ๋ณด์ฐ๋ก๋ณดํฑ์ค
|
| 106 |
+
# '389020', # ์๋ํ
ํฌ๋๋ก์ง
|
| 107 |
+
# '161580', # ํ์ตํฑ์ค
|
| 108 |
+
# '232140', # ์์ด์จ
|
| 109 |
+
# '033100', # ์ ๋ฃก์ ๊ธฐ
|
| 110 |
+
# '031980', # ํผ์์ค์ผ์ดํ๋ฉ์ค
|
| 111 |
+
# '403870', # HPSP
|
| 112 |
+
# '183300', # ์ฝ๋ฏธ์ฝ
|
| 113 |
+
# '445090', # ์์ด์ง๋๋
|
| 114 |
+
'347850', # ๋์ค๋ํ๋งํ
|
| 115 |
+
# '030530', # ์์ตํ๋ฉ์ค
|
| 116 |
+
# '399720', # ๊ฐ์จ์นฉ์ค
|
| 117 |
+
# '042700', # ํ๋ฏธ๋ฐ๋์ฒด
|
| 118 |
+
# '440110', # ํ๋
|
| 119 |
+
# '039030', # ์ด์คํ
ํฌ๋์ค
|
| 120 |
],
|
| 121 |
}
|
| 122 |
|
|
|
|
| 139 |
TREND_MIN_GAP = 0.05 # '240์ฌ': ๋งค๋์ผ ์ข
๊ฐ๊ฐ 240์ +5% ์ด์
|
| 140 |
|
| 141 |
# --- ๋งค๋ ์๋ ์ต์ ํํฐ (์์ฒญ์ฌํญ) ---
|
| 142 |
+
SKIP_IF_BELOW_240 = True # ๋งค๋ ์์ 240์ 'ํ์ฐธ' ์๋๋ฉด ์๋ ๋ (์ด๋ฏธ ๋ฆ์). ๊ทผ์ฒ๋ ์ด๋ฆผ(์๋ TOL)
|
| 143 |
+
BELOW_240_TOL = 0.08 # โ
240์ ๊ทผ์ฒ ํ์ฉ: ์ข
๊ฐ๊ฐ 240์ -TOL ์ด๋ด(ํฐ์น~-8%)๋ฉด '๊ทผ์ฒ'๋ก ๋ณด๊ณ ์๋ ์ด๋ฆผ.
|
| 144 |
+
# ์ด๋ณด๋ค ๋ ๊น์ด(-8% ์ด๊ณผ) ์๋์์ ์ธ๋ฆฐ ๊ฑด 'ํ์ฐธ ์๋'=๋ฆ์์ ํธ๋ก ์คํต(์ฌ์ ํ์)
|
| 145 |
+
# (๋์ค๋ 2026-07 ์ ํธ๊ฐ 240 ๋๋น ์ฝ -6~7%๋ผ 8%๋ก ์ก์. ์กฐ์ ๊ฐ๋ฅ)
|
| 146 |
SKIP_IF_NO_240 = True # 240์ ์ด ์์ผ๋ฉด(๋ฐ์ดํฐ ๋ถ์กฑ) ์๋ ๋
|
| 147 |
MAX_EARLY_DAYS = 129 # ๋งค๋ ํ ์ด ์ผ์๊น์ง๋ง ์ ํจ. ์ด๋ณด๋ค ๋ฆ๊ฒ(130์ผ+) 240์ดํํ๋ฉด
|
| 148 |
# = ๋๋ฌด ์ผ์ฐ ํ ๊ฒ -> ์๋ ๋. (None์ด๋ฉด ์ด ํํฐ ๋)
|
| 149 |
SKIP_IF_STILL_UP = True # ๋งค๋ ํ ๊ด์ฐฐ๊ธฐ๊ฐ ๋ด๋ด 240 ์ ๊นจ๊ณ ์ถ์ธ์ ์ง=ํ๋งค๋(false alarm) -> ์๋ ๋
|
| 150 |
|
| 151 |
+
ANALYZE_FROM = '2010-01-01' # ์ฑ์ (๋งค๋์ง๊ณ) ์์์ผ โ ์ด๊ฑด '์ธ์ ๋ถํฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ์ง'์ผ ๋ฟ
|
| 152 |
ANALYZE_TO = None # None=์ค๋
|
| 153 |
|
| 154 |
# โ
๋ฐ์ดํฐ ๋ก๋ฉ์ ANALYZE_FROM ๊ณผ ๋ฌด๊ดํ๊ฒ 'ํญ์ ์ถฉ๋ถํ ๊ณผ๊ฑฐ๋ถํฐ' ๋ถ๋ฌ์จ๋ค.
|
| 155 |
# (๊ณ ์ /์ด๊ฒฉ์ ์ ์ฒด ๊ฐ๊ฒฉ์ด๋ ฅ์ผ๋ก ๊ณ์ฐ๋ผ์ผ ํ๋ฏ๋ก. ANALYZE_FROM ๋ง ๋ฆ์ถ๋ฉด ๊ณ ์ ์
|
| 156 |
# ์๋ชป ์ก์ ๋งค๋์์ ์ด ๋ฌ๋ผ์ง๋ ๋ฒ๊ทธ๊ฐ ์๊น -> ๊ทธ๋์ DATA_START ๋ ๊ณ ์ .)
|
| 157 |
+
DATA_START = '2008-01-01' # ๊ณ ์ . ๋ ๊ณผ๊ฑฐ๋ฅผ ๋ณด๋ ค๋ฉด ์ด ๋ ์ง๋ง ์๋น๊ธฐ๋ฉด ๋จ.
|
| 158 |
|
| 159 |
|
| 160 |
def _end_date():
|
|
|
|
| 328 |
m = ma240[i]
|
| 329 |
if np.isnan(m):
|
| 330 |
return ('UNKNOWN', None)
|
| 331 |
+
if low[i] <= m: # ์ฅ์ค ์ ๊ฐ๊ฐ 240์ ํฐ์น/์ดํ
|
| 332 |
+
depth = (m - price) / m # ์ข
๊ฐ๊ฐ 240๋ณด๋ค ์ผ๋ง๋ ์๋ (์์=์๋, ์์=์ข
๊ฐ๋ 240์)
|
| 333 |
+
if depth <= BELOW_240_TOL: # 240 ๊ทผ์ฒ(ํฐ์น ~ -TOL ์ด๋ด) -> ์ด๋ฆผ
|
| 334 |
+
return ('NEAR_240', depth)
|
| 335 |
+
return ('ALREADY_DOWN', depth) # ํ์ฐธ ์๋(-TOL ์ด๊ณผ) -> ๋ฆ์์ ํธ๋ก ์คํต
|
| 336 |
end = min(i + 1 + LOOK_AHEAD, len(stock))
|
| 337 |
for k in range(i + 1, end):
|
| 338 |
if not np.isnan(ma240[k]) and low[k] <= ma240[k]:
|
|
|
|
| 439 |
# cat == 'PENDING' -> ์ต๊ทผ ์ ํธ๋ผ ํ์ ๋ถ๊ฐ -> ์ ๋ ๋์ง ์์(์๋ ์ด๋ฆผ)
|
| 440 |
isP = bool(protected(stock, i, price))
|
| 441 |
is_run = in_240_run(stock, ma240, i)
|
| 442 |
+
if cat == 'NEAR_240':
|
| 443 |
+
b = run if is_run else edge
|
| 444 |
+
b['n'] += 1
|
| 445 |
+
if isP: b['P'] += 1
|
| 446 |
+
where = f"{'240์ฌ' if is_run else '๊ฒฝ๊ณ'}, 240๊ทผ์ฒ({days*100:+.1f}%)"
|
| 447 |
+
elif cat == 'ALREADY_DOWN':
|
| 448 |
down_n += 1
|
| 449 |
+
where = f'240 ํ์ฐธ์๋({days*100:+.1f}%)'
|
| 450 |
elif cat == 'EARLY':
|
| 451 |
b = run if is_run else edge
|
| 452 |
b['n'] += 1; b['E'] += 1
|