refactor: apply portfolio cap and align project docs
Keep the fixed 11-number set intact while adding a second-stage portfolio selection that caps final recommendations to the 70,000 KRW budget, and update docs/data/scripts to match the current project structure and runtime flow. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import json
|
||||
from collections import Counter
|
||||
|
||||
import socket
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from final_filter_params import TRAIN_ALLOW
|
||||
socket.getaddrinfo(socket.gethostname(), None)
|
||||
|
||||
class BallFilter:
|
||||
history_ball_dict = None
|
||||
@@ -16,39 +16,15 @@ class BallFilter:
|
||||
compositeNumber = None
|
||||
|
||||
def __init__(self, lottoHistoryFileName=None):
|
||||
if lottoHistoryFileName is None:
|
||||
return
|
||||
self.history_ball_list = []
|
||||
self.history_ball_no_ymd = {}
|
||||
self.history_ball_no_dict = {}
|
||||
self.history_ball_date_dict = {}
|
||||
self.history_ball_dict = {}
|
||||
path = str(lottoHistoryFileName)
|
||||
|
||||
if path.endswith('.txt'):
|
||||
rows = []
|
||||
with open(path, 'r', encoding='utf-8') as in_fp:
|
||||
for line in in_fp:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
parts = line.split(',')
|
||||
drw_no = int(parts[0])
|
||||
balls = [int(parts[i]) for i in range(1, 7)]
|
||||
rows.append((drw_no, balls))
|
||||
rows.sort(key=lambda x: x[0])
|
||||
for drw_no, balls in rows:
|
||||
sb = sorted(balls)
|
||||
self.history_ball_list.append(sb)
|
||||
self.history_ball_no_dict[str(sb)] = drw_no
|
||||
ymd_key = f'{drw_no:08d}'
|
||||
self.history_ball_date_dict[ymd_key] = drw_no
|
||||
self.history_ball_dict[drw_no] = {'date': '', 'ball': list(sb)}
|
||||
self.history_ball_no_ymd[drw_no] = ymd_key
|
||||
else:
|
||||
in_fp = open(path, 'r', encoding='utf-8')
|
||||
if lottoHistoryFileName is not None:
|
||||
inFp = open(lottoHistoryFileName, 'r', encoding='utf-8')
|
||||
self.history_ball_list = []
|
||||
self.history_ball_no_ymd = {}
|
||||
self.history_ball_no_dict = {}
|
||||
self.history_ball_date_dict = {}
|
||||
self.history_ball_dict = {}
|
||||
while True:
|
||||
line = in_fp.readline()
|
||||
line = inFp.readline()
|
||||
if not line or line == '\n':
|
||||
break
|
||||
data = json.loads(line)
|
||||
@@ -56,27 +32,28 @@ class BallFilter:
|
||||
self.history_ball_no_dict[str(self.history_ball_list[len(self.history_ball_list) - 1])] = data['drwNo']
|
||||
self.history_ball_date_dict[data['drwNoDate'].replace('-', '')] = data['drwNo']
|
||||
self.history_ball_dict[data['drwNo']] = {'date': data['drwNoDate'], 'ball': [data['drwtNo1'], data['drwtNo2'], data['drwtNo3'], data['drwtNo4'], data['drwtNo5'], data['drwtNo6']]}
|
||||
self.history_ball_no_ymd[data['drwNo']] = data['drwNoDate'].replace('-', '')
|
||||
in_fp.close()
|
||||
self.history_ball_no_ymd[data['drwNo']] = data['drwNoDate'].replace('-','')
|
||||
inFp.close()
|
||||
|
||||
ball_avg = {}
|
||||
ball_sum = {}
|
||||
for i in range(len(self.history_ball_list)):
|
||||
win_ball = list(self.history_ball_list[-i])
|
||||
avg = sum(win_ball) / 6
|
||||
if avg not in ball_avg:
|
||||
ball_avg[avg] = 1
|
||||
else:
|
||||
ball_avg[avg] += 1
|
||||
# ball 평균과 합 구하기
|
||||
ball_avg = {}
|
||||
ball_sum = {}
|
||||
for i in range(len(self.history_ball_list)):
|
||||
WIN_BALL = list(self.history_ball_list[-i])
|
||||
avg = sum(WIN_BALL) / 6
|
||||
if avg not in ball_avg:
|
||||
ball_avg[avg] = 1
|
||||
else:
|
||||
ball_avg[avg] += 1
|
||||
|
||||
s = sum(self.history_ball_list[-i])
|
||||
if s in ball_sum:
|
||||
ball_sum[s] += 1
|
||||
else:
|
||||
ball_sum[s] = 1
|
||||
if sum(self.history_ball_list[-i]) in ball_sum:
|
||||
ball_sum[sum(self.history_ball_list[-i])] += 1
|
||||
else:
|
||||
ball_sum[sum(self.history_ball_list[-i])] = 1
|
||||
|
||||
self.primeNumber = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]
|
||||
self.compositeNumber = [4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28, 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45]
|
||||
|
||||
self.primeNumber = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]
|
||||
self.compositeNumber = [4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28, 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45]
|
||||
return
|
||||
|
||||
def getBall(self, no):
|
||||
@@ -808,6 +785,7 @@ class BallFilter:
|
||||
return len(low), len(high)
|
||||
|
||||
def filterOneDigitPattern(self, ball):
|
||||
ball = [8, 18, 22, 31, 40, 44]
|
||||
digit = set()
|
||||
for b in ball:
|
||||
if b % 10 not in digit:
|
||||
@@ -3839,7 +3817,6 @@ class BallFilter:
|
||||
p_ball = p_ball[1:7]
|
||||
|
||||
filter_set = set()
|
||||
A = TRAIN_ALLOW
|
||||
|
||||
### S: 이전 당첨 번호
|
||||
if no is not None:
|
||||
@@ -3852,7 +3829,7 @@ class BallFilter:
|
||||
|
||||
### S: 당첨번호 6개 합
|
||||
acc = sum(ball)
|
||||
if acc not in A.sum6:
|
||||
if acc not in {112,114,121,123,126,127,131,132,138,146,148,156,154,163,165,167,172,174,183}:
|
||||
filter_set.add('6개 합: {}'.format(acc))
|
||||
if not until_end:
|
||||
return filter_set
|
||||
@@ -3860,7 +3837,8 @@ class BallFilter:
|
||||
### E: 당첨번호 6개 합
|
||||
|
||||
### S: 당첨번호 6개 합에 대한 전주와 차이
|
||||
if abs(acc - p_acc) not in A.abs_sum_diff:
|
||||
if abs(acc - p_acc) not in {2,3,4,6,7,8,9,10,11,12,13,14,15,17,18,24,25,26,27,28,29,30,31,32,33,34,39,40,51}:
|
||||
# 첫수와 끝수의 합에 대해서 전주 금주의 차이
|
||||
filter_set.add('6개 합 전주차: {}'.format(abs(acc - p_acc)))
|
||||
if not until_end:
|
||||
return filter_set
|
||||
@@ -4331,6 +4309,7 @@ class BallFilter:
|
||||
if not until_end:
|
||||
return filter_set
|
||||
### E: 홀짝 개수에 대한 전주와 차이
|
||||
|
||||
### S: 용지에 안나올 것 같은 마킹 위치 (filterPatternInPaper1~filterPatternInPaper6)
|
||||
v1 = self.filterPatternInPaper1(ball)
|
||||
v2 = self.filterPatternInPaper2(ball)
|
||||
|
||||
Reference in New Issue
Block a user