glorifiedjx commited on
Commit
ee59593
ยท
verified ยท
1 Parent(s): f380d28

Update confirm_sell_backtest.py

Browse files
Files changed (1) hide show
  1. 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
- # '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
- ],
42
- 'KOSDAQ': [
43
- # '247540', '086520', '196170', '028300', '348370',
44
- # '058470', '068760', '263750', '035900', '277810',
45
- # '041510', '035760', '112040', '293490', '145020',
46
- # '039030', '240810', '357780', '403870', '121600',
47
- # '399720',
48
- '088130',
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 # ๋งค๋„ ์‹œ์  ์ข…๊ฐ€๊ฐ€ 240์„  ์•„๋ž˜๋ฉด ์•Œ๋žŒ ๋” (์ด๋ฏธ ๋Šฆ์Œ)
 
 
 
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 = '2020-01-01' # ์ฑ„์ (๋งค๋„์ง‘๊ณ„) ์‹œ์ž‘์ผ โ€” ์ด๊ฑด '์–ธ์ œ๋ถ€ํ„ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ์ง€'์ผ ๋ฟ
79
  ANALYZE_TO = None # None=์˜ค๋Š˜
80
 
81
  # โ˜… ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ์€ ANALYZE_FROM ๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ 'ํ•ญ์ƒ ์ถฉ๋ถ„ํžˆ ๊ณผ๊ฑฐ๋ถ€ํ„ฐ' ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
82
  # (๊ณ ์ /์ด๊ฒฉ์€ ์ „์ฒด ๊ฐ€๊ฒฉ์ด๋ ฅ์œผ๋กœ ๊ณ„์‚ฐ๋ผ์•ผ ํ•˜๋ฏ€๋กœ. ANALYZE_FROM ๋งŒ ๋Šฆ์ถ”๋ฉด ๊ณ ์ ์„
83
  # ์ž˜๋ชป ์žก์•„ ๋งค๋„์‹œ์ ์ด ๋‹ฌ๋ผ์ง€๋Š” ๋ฒ„๊ทธ๊ฐ€ ์ƒ๊น€ -> ๊ทธ๋ž˜์„œ DATA_START ๋Š” ๊ณ ์ •.)
84
- DATA_START = '2018-01-01' # ๊ณ ์ •. ๋” ๊ณผ๊ฑฐ๋ฅผ ๋ณด๋ ค๋ฉด ์ด ๋‚ ์งœ๋งŒ ์•ž๋‹น๊ธฐ๋ฉด ๋จ.
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
- return ('ALREADY_DOWN', None)
 
 
 
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 == 'ALREADY_DOWN':
 
 
 
 
 
367
  down_n += 1
368
- where = '์ด๋ฏธ240์•„๋ž˜'
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