Initial commit: Korean stock value-investing AI pipeline
- 19개 마이크로서비스 (news-collector, score-engine, ta-engine, dart-collector, aux-signal, us-market, graph-engine, telegram-bot, dashboard-api, kis-api 등) - 가치투자 스코어링 + 10공식 앙상블 보팅 (매직포뮬러/F-Score/Altman/PEG/ 모멘텀/Beneish/GP-A/G-Score/Amihud/BAB) - 뉴스 수집→형태소→임베딩→중복제거→AI분석 파이프라인 - 기술적분석 + GAT 그래프신경망 + 미증시 동조 시그널 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+146
@@ -0,0 +1,146 @@
|
||||
#!/bin/bash
|
||||
# PostgreSQL 로컬 설치 + 데이터 경로를 시놀로지 NAS(/mnt/nas)에 설정
|
||||
# 실행: sudo bash setup-postgres-local.sh
|
||||
|
||||
set -e
|
||||
|
||||
NAS_HOST="192.168.0.36"
|
||||
NAS_NFS_PATH="/volume1/trading"
|
||||
NFS_MOUNT_LOCAL="/mnt/nas"
|
||||
PG_DATA_DIR="${NFS_MOUNT_LOCAL}/postgresql/data"
|
||||
PG_VERSION="16"
|
||||
PG_USER="kyu"
|
||||
PG_PASSWORD="7895123"
|
||||
PG_DB="trading_ai"
|
||||
|
||||
echo "=============================="
|
||||
echo "1. NFS 클라이언트 설치 확인"
|
||||
echo "=============================="
|
||||
apt-get install -y nfs-common 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "2. NAS NFS 마운트"
|
||||
echo "=============================="
|
||||
mkdir -p "${NFS_MOUNT_LOCAL}"
|
||||
|
||||
# 이미 마운트 되어있으면 스킵
|
||||
if mountpoint -q "${NFS_MOUNT_LOCAL}"; then
|
||||
echo "이미 마운트됨: ${NFS_MOUNT_LOCAL}"
|
||||
else
|
||||
mount -t nfs "${NAS_HOST}:${NAS_NFS_PATH}" "${NFS_MOUNT_LOCAL}" -o rw,hard,intr,timeo=30,retrans=3
|
||||
echo "마운트 완료: ${NAS_HOST}:${NAS_NFS_PATH} -> ${NFS_MOUNT_LOCAL}"
|
||||
fi
|
||||
|
||||
# /etc/fstab에 자동 마운트 등록 (없으면 추가)
|
||||
FSTAB_ENTRY="${NAS_HOST}:${NAS_NFS_PATH} ${NFS_MOUNT_LOCAL} nfs rw,hard,intr,timeo=30,retrans=3,_netdev 0 0"
|
||||
if ! grep -qF "${NFS_MOUNT_LOCAL}" /etc/fstab; then
|
||||
echo "${FSTAB_ENTRY}" >> /etc/fstab
|
||||
echo "fstab에 자동 마운트 추가됨"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "3. PostgreSQL 데이터 디렉토리 생성"
|
||||
echo "=============================="
|
||||
mkdir -p "${PG_DATA_DIR}"
|
||||
chown postgres:postgres "${PG_DATA_DIR}"
|
||||
chmod 700 "${PG_DATA_DIR}"
|
||||
echo "데이터 경로: ${PG_DATA_DIR}"
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "4. PostgreSQL 서비스 설정"
|
||||
echo "=============================="
|
||||
|
||||
# 기존 클러스터 중지 및 제거
|
||||
pg_ctlcluster ${PG_VERSION} main stop 2>/dev/null || true
|
||||
|
||||
# 기존 기본 데이터 디렉토리를 NAS 경로로 교체
|
||||
CONF_FILE="/etc/postgresql/${PG_VERSION}/main/postgresql.conf"
|
||||
if [ -f "${CONF_FILE}" ]; then
|
||||
# data_directory 변경
|
||||
sed -i "s|^data_directory.*|data_directory = '${PG_DATA_DIR}'|" "${CONF_FILE}"
|
||||
# 이미 변경된 경우가 아니면 추가
|
||||
if ! grep -q "^data_directory" "${CONF_FILE}"; then
|
||||
echo "data_directory = '${PG_DATA_DIR}'" >> "${CONF_FILE}"
|
||||
fi
|
||||
echo "postgresql.conf 업데이트 완료"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "5. 데이터 디렉토리 초기화 (최초 1회)"
|
||||
echo "=============================="
|
||||
if [ ! -f "${PG_DATA_DIR}/PG_VERSION" ]; then
|
||||
sudo -u postgres /usr/lib/postgresql/${PG_VERSION}/bin/initdb \
|
||||
-D "${PG_DATA_DIR}" \
|
||||
--encoding=UTF8 \
|
||||
--locale=ko_KR.UTF-8 \
|
||||
--auth=md5 2>/dev/null || \
|
||||
sudo -u postgres /usr/lib/postgresql/${PG_VERSION}/bin/initdb \
|
||||
-D "${PG_DATA_DIR}" \
|
||||
--encoding=UTF8 \
|
||||
--locale=C.UTF-8 \
|
||||
--auth=md5
|
||||
echo "DB 초기화 완료"
|
||||
else
|
||||
echo "이미 초기화된 데이터 디렉토리 (스킵)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "6. 외부 접속 허용 설정"
|
||||
echo "=============================="
|
||||
# postgresql.conf - 모든 인터페이스 리슨
|
||||
sed -i "s|^#listen_addresses.*|listen_addresses = '*'|; s|^listen_addresses.*|listen_addresses = '*'|" "${PG_DATA_DIR}/postgresql.conf" 2>/dev/null || \
|
||||
echo "listen_addresses = '*'" >> "${PG_DATA_DIR}/postgresql.conf"
|
||||
|
||||
# pg_hba.conf - Docker 네트워크(172.30.0.0/16) 접속 허용
|
||||
PG_HBA="${PG_DATA_DIR}/pg_hba.conf"
|
||||
if ! grep -q "172.30.0.0/16" "${PG_HBA}" 2>/dev/null; then
|
||||
cat >> "${PG_HBA}" << 'HBA'
|
||||
# Trading AI Docker 네트워크
|
||||
host all all 172.30.0.0/16 md5
|
||||
host all all 127.0.0.1/32 md5
|
||||
host all all ::1/128 md5
|
||||
HBA
|
||||
echo "pg_hba.conf 업데이트 완료"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "7. PostgreSQL 서비스 시작"
|
||||
echo "=============================="
|
||||
systemctl start postgresql
|
||||
systemctl enable postgresql
|
||||
sleep 3
|
||||
systemctl is-active postgresql && echo "PostgreSQL 실행 중"
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "8. 유저 및 DB 생성"
|
||||
echo "=============================="
|
||||
sudo -u postgres psql -c "DO \$\$ BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${PG_USER}') THEN
|
||||
CREATE USER ${PG_USER} WITH SUPERUSER PASSWORD '${PG_PASSWORD}';
|
||||
ELSE
|
||||
ALTER USER ${PG_USER} WITH PASSWORD '${PG_PASSWORD}';
|
||||
END IF;
|
||||
END \$\$;"
|
||||
|
||||
sudo -u postgres psql -c "CREATE DATABASE ${PG_DB} OWNER ${PG_USER};" 2>/dev/null || \
|
||||
echo "DB ${PG_DB} 이미 존재 (스킵)"
|
||||
|
||||
echo ""
|
||||
echo "=============================="
|
||||
echo "완료! PostgreSQL 로컬 실행 중"
|
||||
echo " Host: localhost (또는 127.0.0.1)"
|
||||
echo " Port: 5432"
|
||||
echo " DB: ${PG_DB}"
|
||||
echo " User: ${PG_USER}"
|
||||
echo " Data: ${PG_DATA_DIR} (NAS)"
|
||||
echo "=============================="
|
||||
echo ""
|
||||
echo "다음 단계: 덤프 임포트"
|
||||
echo " PGPASSWORD=${PG_PASSWORD} psql -h 127.0.0.1 -U ${PG_USER} -d ${PG_DB} -f /home/kyu/trading/pg_backup/trading_ai_backup.sql"
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# Trading AI - Setup Script
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
log() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
||||
err() { echo -e "${RED}[✗]${NC} $1" >&2; exit 1; }
|
||||
|
||||
[ -f .env ] && source .env || err ".env 파일이 없습니다."
|
||||
|
||||
echo "============================================================"
|
||||
echo " Trading AI System - Setup"
|
||||
echo "============================================================"
|
||||
|
||||
# ── 1. Docker / NVIDIA 확인 ────────────────────────────────
|
||||
command -v docker >/dev/null 2>&1 || err "Docker가 없습니다."
|
||||
|
||||
if ! command -v nvidia-smi >/dev/null 2>&1; then
|
||||
err "NVIDIA 드라이버가 없습니다."
|
||||
fi
|
||||
|
||||
if ! docker info 2>/dev/null | grep -q "Runtimes.*nvidia"; then
|
||||
warn "nvidia-container-toolkit 설치 중..."
|
||||
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
|
||||
sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
|
||||
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
|
||||
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
|
||||
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y nvidia-container-toolkit
|
||||
sudo nvidia-ctk runtime configure --runtime=docker
|
||||
sudo systemctl restart docker
|
||||
log "nvidia-container-toolkit 설치 완료"
|
||||
fi
|
||||
|
||||
log "GPU 정보:"
|
||||
nvidia-smi --query-gpu=index,name,memory.total --format=csv,noheader | \
|
||||
while IFS=, read -r idx name mem; do echo " GPU $idx: $name ($mem)"; done
|
||||
|
||||
# ── 2. 시스템 최적화 ────────────────────────────────────────
|
||||
if ! grep -q "vm.overcommit_memory" /etc/sysctl.conf 2>/dev/null; then
|
||||
printf "vm.overcommit_memory = 1\nvm.swappiness = 10\nnet.core.somaxconn = 65535\n" | \
|
||||
sudo tee -a /etc/sysctl.conf
|
||||
sudo sysctl -p >/dev/null 2>&1
|
||||
log "커널 파라미터 최적화"
|
||||
fi
|
||||
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled >/dev/null
|
||||
|
||||
# ── 3. NFS 마운트 (스킵 - 나중에 수동 설정) ───────────────
|
||||
warn "NFS 마운트 스킵 (Synology 설정 후 수동으로 진행하세요)"
|
||||
sudo mkdir -p /mnt/nas/news /mnt/nas/models /mnt/nas/backups
|
||||
# ── 4. 기존 네트워크 정리 ──────────────────────────────────
|
||||
log "기존 컨테이너/네트워크 정리 중..."
|
||||
docker compose down --remove-orphans 2>/dev/null || true
|
||||
docker network prune -f >/dev/null 2>&1 || true
|
||||
|
||||
# ── 5. 순차 시작 ───────────────────────────────────────────
|
||||
log "1단계: Redis, Qdrant, Bareun 시작..."
|
||||
docker compose up -d --build redis qdrant bareun
|
||||
|
||||
log "헬스체크 대기 (20초)..."
|
||||
sleep 20
|
||||
|
||||
log "2단계: bareunaapi 시작..."
|
||||
docker compose up -d --build bareunaapi
|
||||
|
||||
log "3단계: Ollama 시작 (GPU 1 - RTX 3070)..."
|
||||
docker compose up -d ollama
|
||||
|
||||
log "BGE-M3 모델 다운로드 중..."
|
||||
sleep 30
|
||||
docker exec trading-ollama ollama pull bge-m3 2>/dev/null || \
|
||||
warn "BGE-M3 수동 다운로드 필요: docker exec trading-ollama ollama pull bge-m3"
|
||||
|
||||
log "4단계: vLLM 시작 (GPU 0 - RTX 3060, 모델 로딩 2~5분)..."
|
||||
docker compose up -d vllm
|
||||
|
||||
log "5단계: n8n 시작..."
|
||||
docker compose up -d n8n n8n-worker
|
||||
|
||||
# ── 6. Qdrant 컬렉션 초기화 ────────────────────────────────
|
||||
log "Qdrant 컬렉션 초기화 중..."
|
||||
sleep 10
|
||||
HTTP=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:6333/collections/news_vectors)
|
||||
if [ "${HTTP}" = "404" ]; then
|
||||
curl -s -X PUT http://localhost:6333/collections/news_vectors \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"vectors": {"size": 1024, "distance": "Cosine"},
|
||||
"optimizers_config": {"default_segment_number": 4},
|
||||
"on_disk_payload": false
|
||||
}' >/dev/null
|
||||
log "Qdrant 컬렉션 'news_vectors' 생성"
|
||||
else
|
||||
warn "Qdrant 컬렉션 이미 존재"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo -e "${GREEN} 시작 완료!${NC}"
|
||||
echo "============================================================"
|
||||
echo " n8n : http://localhost:5678"
|
||||
echo " Qdrant : http://localhost:6333/dashboard"
|
||||
echo " vLLM : http://localhost:8000/docs"
|
||||
echo " Ollama : http://localhost:11434"
|
||||
echo " 바른API : http://localhost:5757/docs"
|
||||
echo "============================================================"
|
||||
warn "vLLM 모델 로딩 확인: docker compose logs -f vllm"
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
[ -f .env ] && source .env
|
||||
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||||
|
||||
chk_http() {
|
||||
local name=$1 url=$2
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 4 "$url" 2>/dev/null || echo "000")
|
||||
[[ "$code" =~ ^(200|204)$ ]] \
|
||||
&& echo -e " ${GREEN}●${NC} $name" \
|
||||
|| echo -e " ${RED}●${NC} $name (HTTP $code)"
|
||||
}
|
||||
|
||||
chk_container() {
|
||||
local name=$1
|
||||
status=$(docker inspect --format='{{.State.Status}}' "$name" 2>/dev/null || echo "없음")
|
||||
[ "$status" = "running" ] \
|
||||
&& echo -e " ${GREEN}●${NC} $name" \
|
||||
|| echo -e " ${RED}●${NC} $name ($status)"
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}══ Trading AI Status ══════════════════════${NC} $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
|
||||
echo -e "\n${BLUE}[컨테이너]${NC}"
|
||||
for c in trading-redis trading-qdrant trading-bareun trading-bareunaapi \
|
||||
trading-ollama trading-vllm trading-n8n trading-n8n-worker; do
|
||||
chk_container "$c"
|
||||
done
|
||||
|
||||
echo -e "\n${BLUE}[서비스]${NC}"
|
||||
chk_http "Redis" "http://localhost:6379"
|
||||
chk_http "Qdrant" "http://localhost:6333/healthz"
|
||||
chk_http "Bareun" "http://localhost:9902/health"
|
||||
chk_http "바른API" "http://localhost:5757/health"
|
||||
chk_http "Ollama" "http://localhost:11434/api/tags"
|
||||
chk_http "vLLM" "http://localhost:8000/health"
|
||||
chk_http "n8n" "http://localhost:5678/healthz"
|
||||
|
||||
echo -e "\n${BLUE}[GPU]${NC}"
|
||||
nvidia-smi --query-gpu=index,name,utilization.gpu,memory.used,memory.total,temperature.gpu \
|
||||
--format=csv,noheader 2>/dev/null | \
|
||||
while IFS=, read -r i n u mu mt t; do
|
||||
echo " GPU$i $n | 사용률:$u | VRAM:$mu/$mt | 온도:$t"
|
||||
done
|
||||
|
||||
echo -e "\n${BLUE}[NFS]${NC}"
|
||||
mountpoint -q /mnt/nas 2>/dev/null \
|
||||
&& echo -e " ${GREEN}●${NC} /mnt/nas (마운트됨)" \
|
||||
|| echo -e " ${RED}●${NC} /mnt/nas (마운트 안됨)"
|
||||
|
||||
echo ""
|
||||
Reference in New Issue
Block a user