게시판Qwen2.5-VL 차트 LoRA: PNG로 매수·매도·유지 학습하기예제 소스

예제 소스

Qwen2.5-VL 차트 LoRA: PNG로 매수·매도·유지 학습하기 · 파일 59개

chart_png.py

"""차트 PNG 경로: ``chart/{bucket:04d}/{bar:07d}.png``.

한 폴더에 파일이 너무 많으면 macOS fseventsd/Spotlight 가 CPU 를 먹는다.
bucket = bar_index // 10000 이라 폴더당 최대 10000장이다.
"""

from __future__ import annotations

import os
from collections.abc import Iterator
from pathlib import Path

CHART_BUCKET_SIZE = 10_000


def chart_bucket(bar: int) -> int:
    return int(bar) // CHART_BUCKET_SIZE


def chart_png_path(chart_dir: Path | str, bar: int) -> Path:
    bar = int(bar)
    return Path(chart_dir) / f"{chart_bucket(bar):04d}" / f"{bar:07d}.png"


def iter_chart_pngs(chart_dir: Path | str) -> Iterator[Path]:
    root = Path(chart_dir)
    if not root.is_dir():
        return
    with os.scandir(root) as it:
        for entry in it:
            if entry.is_file() and entry.name.endswith(".png"):
                stem = entry.name[:-4]
                if stem.isdigit():
                    yield Path(entry.path)
                continue
            if not entry.is_dir() or not entry.name.isdigit():
                continue
            with os.scandir(entry.path) as nested:
                for child in nested:
                    if not child.is_file() or not child.name.endswith(".png"):
                        continue
                    stem = child.name[:-4]
                    if stem.isdigit():
                        yield Path(child.path)


def existing_chart_bars(chart_dir: Path | str) -> set[int]:
    have: set[int] = set()
    for path in iter_chart_pngs(chart_dir):
        try:
            if path.stat().st_size > 0:
                have.add(int(path.stem))
        except OSError:
            continue
    return have


def migrate_flat_chart_dir(chart_dir: Path | str, *, log=None) -> tuple[int, int]:
    """루트의 ``NNNNNNN.png`` 를 버킷 폴더로 옮긴다. 이미 버킷에 있으면 건너뛴다."""
    root = Path(chart_dir)
    if not root.is_dir():
        return 0, 0
    names: list[str] = []
    with os.scandir(root) as it:
        for entry in it:
            if entry.is_file() and entry.name.endswith(".png") and entry.name[:-4].isdigit():
                names.append(entry.name)
    if log is not None:
        log("flat png %s장 목록 확보", len(names))
    moved = 0
    skipped = 0
    made: set[str] = set()
    for n, name in enumerate(names, start=1):
        dest = chart_png_path(root, int(name[:-4]))
        parent = str(dest.parent)
        if parent not in made:
            dest.parent.mkdir(parents=True, exist_ok=True)
            made.add(parent)
        src = os.path.join(str(root), name)
        if os.path.lexists(dest):
            skipped += 1
            continue
        os.rename(src, dest)
        moved += 1
        if log is not None and (moved == 1 or moved % 1000 == 0):
            log("moved %s / scanned %s → %s", moved, n, dest)
    return moved, skipped