Files
stocksearch/services/db.go
hayato5246 ba18887ed8
Some checks failed
Build Push and Restart Compose / deploy (push) Failing after 1m47s
PostgreSQL 의존성 및 내부 유틸리티 추가:
- `github.com/lib/pq` PostgreSQL 드라이버 vendor 디렉토리에 추가.
- PostgreSQL 관련 내부 패키지(`pqsql`, `proto`, `pqtime`, `pgpass`, `pgservice`, `pqutil`) 구현:
  - SQL 어휘 처리, 프로토콜 상수 및 구조 정의, 시간 파서/포맷터(`Parse`, `Format`).
  - `.pgpass` 파일 및 `pg_service.conf` 관리 기능 추가.
  - 파일/사용자 권한 검증 및 플랫폼별 사용자 정보 조회 기능 포함.
- 데이터베이스 초기화 로직 추가 (`services/db.go`):
  - PostgreSQL 연결 설정 및 초기 스키마 생성.
- 자동매매 관련 DB 레포지토리(`services/autotrade_repo.go`) 구현:
  - 자동매매 규칙 및 포지션 관리 로직 추가 (`dbInsertRule`, `dbLoadRules` 등).
2026-04-08 19:07:32 +09:00

102 lines
3.0 KiB
Go

package services
import (
"database/sql"
"log"
"stocksearch/config"
_ "github.com/lib/pq"
)
var db *sql.DB
// InitDB PostgreSQL 연결 초기화 및 스키마 생성
func InitDB() {
dsn := config.App.DatabaseURL
if dsn == "" {
log.Println("DATABASE_URL 미설정 — DB 없이 메모리 모드로 동작")
return
}
var err error
db, err = sql.Open("postgres", dsn)
if err != nil {
log.Fatalf("DB 연결 실패: %v", err)
}
if err = db.Ping(); err != nil {
log.Fatalf("DB ping 실패: %v", err)
}
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(5)
createTables()
log.Println("PostgreSQL 연결 완료")
}
// GetDB DB 인스턴스 반환 (nil이면 DB 미사용)
func GetDB() *sql.DB {
return db
}
func createTables() {
schema := `
CREATE TABLE IF NOT EXISTS autotrade_rules (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT true,
min_rise_score INTEGER NOT NULL DEFAULT 60,
min_cntr_str REAL NOT NULL DEFAULT 110,
require_bullish BOOLEAN NOT NULL DEFAULT false,
order_amount BIGINT NOT NULL DEFAULT 1000000,
max_positions INTEGER NOT NULL DEFAULT 3,
stop_loss1_pct REAL NOT NULL DEFAULT -2.0,
stop_loss1_count INTEGER NOT NULL DEFAULT 3,
stop_loss_pct REAL NOT NULL DEFAULT -4.0,
take_profit_pct REAL NOT NULL DEFAULT 5.0,
max_hold_minutes INTEGER NOT NULL DEFAULT 60,
exit_before_close BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS autotrade_positions (
id SERIAL PRIMARY KEY,
code TEXT NOT NULL,
name TEXT NOT NULL DEFAULT '',
buy_price BIGINT NOT NULL DEFAULT 0,
qty BIGINT NOT NULL DEFAULT 0,
order_no TEXT NOT NULL DEFAULT '',
entry_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
rule_id TEXT NOT NULL DEFAULT '',
stop_loss1 BIGINT NOT NULL DEFAULT 0,
stop_loss1_touches INTEGER NOT NULL DEFAULT 0,
stop_loss BIGINT NOT NULL DEFAULT 0,
take_profit BIGINT NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'pending',
exit_time TIMESTAMPTZ,
exit_price BIGINT NOT NULL DEFAULT 0,
exit_reason TEXT NOT NULL DEFAULT ''
);
CREATE INDEX IF NOT EXISTS idx_positions_status ON autotrade_positions(status);
CREATE INDEX IF NOT EXISTS idx_positions_exit_time ON autotrade_positions(exit_time);
CREATE TABLE IF NOT EXISTS autotrade_logs (
id SERIAL PRIMARY KEY,
at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
level TEXT NOT NULL DEFAULT 'info',
message TEXT NOT NULL DEFAULT '',
code TEXT NOT NULL DEFAULT ''
);
CREATE INDEX IF NOT EXISTS idx_logs_at ON autotrade_logs(at);
CREATE TABLE IF NOT EXISTS autotrade_watch_source (
id INTEGER PRIMARY KEY DEFAULT 1,
use_scanner BOOLEAN NOT NULL DEFAULT true,
selected_themes JSONB NOT NULL DEFAULT '[]'
);
`
if _, err := db.Exec(schema); err != nil {
log.Fatalf("스키마 생성 실패: %v", err)
}
}