glorifiedjx commited on
Commit
8875a0d
·
verified ·
1 Parent(s): 96beb36

back to stage

Browse files
Files changed (1) hide show
  1. confirm_sell_backtest.py +24 -15
confirm_sell_backtest.py CHANGED
@@ -19,7 +19,9 @@ import sys, ssl
19
  import pandas as pd
20
  import numpy as np
21
  import FinanceDataReader as fdr
22
- from datetime import datetime, timedelta
 
 
23
 
24
  ssl._create_default_https_context = ssl._create_unverified_context
25
  if sys.platform == 'win32':
@@ -39,15 +41,10 @@ TICKERS = {
39
  ],
40
  'KOSDAQ': [
41
  # '247540', '086520', '196170', '028300', '348370',
42
- # '058470', '068760', '263750', '035900',
43
- # '277810',
44
- '234690',
45
  # '041510', '035760', '112040', '293490', '145020',
46
- # '039030', '240810', '357780',
47
- # '403870',
48
- # '121600',
49
- # '399720',
50
- # '234340',
51
  ],
52
  }
53
 
@@ -80,8 +77,12 @@ ANALYZE_TO = None # None=오늘
80
  # 잘못 잡아 매도시점이 달라지는 버그가 생김 -> 그래서 DATA_START 는 고정.)
81
  DATA_START = '2018-01-01' # 고정. 더 과거를 보려면 이 날짜만 앞당기면 됨.
82
 
83
- _to_dt = datetime.strptime(ANALYZE_TO, '%Y-%m-%d') if ANALYZE_TO else datetime.today()
84
- ANALYZE_TO = _to_dt.strftime('%Y-%m-%d')
 
 
 
 
85
 
86
 
87
  # =============================================
@@ -103,8 +104,9 @@ def _trailing_peaks(stock, index, win):
103
  return pk, ipk
104
 
105
 
106
- def find_confirmed_sells(stock, index, dates, start_pos):
107
  """확정매도(2차) 찾기 — 단계별 누적 하락 + 하루 이격 급변 점프.
 
108
  고점 = '최근 PEAK_WINDOW(252) 거래일 내 최고점' (트레일링).
109
  단계: flagON(대기) -> 1차(확정) -> 2차flagON(대기) -> 2차매도(확정)
110
  - 평소: 직전 단계보다 이격 MIN_DEEPEN(2.5%p)+ 더 깊으면 다음 단계
@@ -180,6 +182,13 @@ def find_confirmed_sells(stock, index, dates, start_pos):
180
  sells.append({'i': t, 'price': st, 'div': div, 'date': dates[t]})
181
  sold = True
182
  prev_div = div
 
 
 
 
 
 
 
183
  return sells, jumps
184
 
185
 
@@ -220,7 +229,7 @@ def protected(stock, i, price):
220
 
221
  def load_one(ticker, market):
222
  try:
223
- sdf = fdr.DataReader(ticker, DATA_START, ANALYZE_TO)
224
  except Exception:
225
  return None
226
  if not isinstance(sdf, pd.DataFrame) or 'Close' not in sdf.columns or len(sdf) == 0:
@@ -229,7 +238,7 @@ def load_one(ticker, market):
229
  idf = None
230
  for c in (idx_code, '^' + idx_code):
231
  try:
232
- t = fdr.DataReader(c, DATA_START, ANALYZE_TO)
233
  if isinstance(t, pd.DataFrame) and 'Close' in t.columns and len(t) > 0:
234
  idf = t; break
235
  except Exception:
@@ -261,7 +270,7 @@ def pct(a, b):
261
 
262
  def main():
263
  print("=" * 88)
264
- print(f"이격 재확인 백테스트 [lower-low] | {ANALYZE_FROM} ~ {ANALYZE_TO} | 종목 "
265
  f"{sum(len(v) for v in TICKERS.values())}개")
266
  print(f"규칙: 고점=최근{PEAK_WINDOW}일내최고 | 단계누적({MIN_DEEPEN*100:.1f}%p+) | 하루급변({DAILY_JUMP*100:.0f}%p)점프 | 1차~2차 22일내 | 회복시재시작")
267
  print(f"채점: 관찰 {LOOK_AHEAD}일 | E율=240이탈(조기경보) | P율=매도가대비 {PROTECT_DROP*100:.0f}% 추가하락 회피")
 
19
  import pandas as pd
20
  import numpy as np
21
  import FinanceDataReader as fdr
22
+ from datetime import datetime, timedelta, timezone
23
+
24
+ _KST = timezone(timedelta(hours=9))
25
 
26
  ssl._create_default_https_context = ssl._create_unverified_context
27
  if sys.platform == 'win32':
 
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
  ],
49
  }
50
 
 
77
  # 잘못 잡아 매도시점이 달라지는 버그가 생김 -> 그래서 DATA_START 는 고정.)
78
  DATA_START = '2018-01-01' # 고정. 더 과거를 보려면 이 날짜만 앞당기면 됨.
79
 
80
+
81
+ def _end_date():
82
+ """데이터 끝날짜. ANALYZE_TO=None이면 매번 '지금 KST 오늘'로 계산(앱 켜둬도 최신)."""
83
+ if ANALYZE_TO:
84
+ return ANALYZE_TO
85
+ return datetime.now(_KST).strftime('%Y-%m-%d')
86
 
87
 
88
  # =============================================
 
104
  return pk, ipk
105
 
106
 
107
+ def find_confirmed_sells(stock, index, dates, start_pos, return_state=False):
108
  """확정매도(2차) 찾기 — 단계별 누적 하락 + 하루 이격 급변 점프.
109
+ return_state=True면 (sells, jumps, state) 반환. state=현재(마지막) 단계/이격.
110
  고점 = '최근 PEAK_WINDOW(252) 거래일 내 최고점' (트레일링).
111
  단계: flagON(대기) -> 1차(확정) -> 2차flagON(대기) -> 2차매도(확정)
112
  - 평소: 직전 단계보다 이격 MIN_DEEPEN(2.5%p)+ 더 깊으면 다음 단계
 
182
  sells.append({'i': t, 'price': st, 'div': div, 'date': dates[t]})
183
  sold = True
184
  prev_div = div
185
+ if return_state:
186
+ last = n - 1
187
+ cur_div = (float(stock[last]) / float(twpk[last]) - 1) \
188
+ - ((float(index[last]) / float(twip[last]) - 1) if twip[last] else 0.0)
189
+ state = {'stage': stage, 'stage_name': _SNAME.get(stage, '?'),
190
+ 'div': cur_div, 'sold': sold}
191
+ return sells, jumps, state
192
  return sells, jumps
193
 
194
 
 
229
 
230
  def load_one(ticker, market):
231
  try:
232
+ sdf = fdr.DataReader(ticker, DATA_START, _end_date())
233
  except Exception:
234
  return None
235
  if not isinstance(sdf, pd.DataFrame) or 'Close' not in sdf.columns or len(sdf) == 0:
 
238
  idf = None
239
  for c in (idx_code, '^' + idx_code):
240
  try:
241
+ t = fdr.DataReader(c, DATA_START, _end_date())
242
  if isinstance(t, pd.DataFrame) and 'Close' in t.columns and len(t) > 0:
243
  idf = t; break
244
  except Exception:
 
270
 
271
  def main():
272
  print("=" * 88)
273
+ print(f"이격 재확인 백테스트 [lower-low] | {ANALYZE_FROM} ~ {_end_date()} | 종목 "
274
  f"{sum(len(v) for v in TICKERS.values())}개")
275
  print(f"규칙: 고점=최근{PEAK_WINDOW}일내최고 | 단계누적({MIN_DEEPEN*100:.1f}%p+) | 하루급변({DAILY_JUMP*100:.0f}%p)점프 | 1차~2차 22일내 | 회복시재시작")
276
  print(f"채점: 관찰 {LOOK_AHEAD}일 | E율=240이탈(조기경보) | P율=매도가대비 {PROTECT_DROP*100:.0f}% 추가하락 회피")