File size: 4,159 Bytes
a600665 381775d 5840851 a600665 5840851 a600665 5840851 a600665 5840851 a600665 5840851 a600665 5840851 a600665 5840851 a600665 5840851 a600665 5840851 381775d 5840851 8200518 5840851 8200518 5840851 8200518 a600665 5840851 8200518 5840851 ffd99f4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | from datetime import datetime, timedelta
from sqlalchemy import Column, String, Integer, Float, Boolean, DateTime, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class Company(Base):
"""์์ฅ์ฌ ๊ธฐ๋ณธ ์ ๋ณด. ์ฐ์ ์ฃผ๋ ์์ง ์ skip."""
__tablename__ = "company"
ticker = Column(String, primary_key=True)
corp_code = Column(String) # DART corp_code (8์๋ฆฌ)
name = Column(String, nullable=False)
market = Column(String) # KOSPI / KOSDAQ
fiscal_year_end = Column(Integer, default=12) # ๊ฒฐ์ฐ์ (12=12์ ๊ฒฐ์ฐ)
class PriceSnapshot(Base):
"""ํ์ฌ ์ฃผ๊ฐ + ์๊ฐ์ด์ก. ๋ค์ด๋ฒ ์ปจ์ผ์์ค ์์ง ์ ํจ๊ป ์ ์ฅ."""
__tablename__ = "price_snapshot"
ticker = Column(String, ForeignKey("company.ticker"), primary_key=True)
current_price = Column(Float)
market_cap = Column(Float) # ์ต์
updated_at = Column(DateTime)
class AnnualData(Base):
"""์ฐ๊ฐ ์ฌ๋ฌด ๋ฐ์ดํฐ. ํ์ ์ค์ (is_estimate=False)๊ณผ ์ปจ์ผ์์ค(is_estimate=True) ํตํฉ."""
__tablename__ = "annual_data"
id = Column(Integer, primary_key=True, autoincrement=True)
ticker = Column(String, ForeignKey("company.ticker"), nullable=False)
year = Column(Integer, nullable=False)
is_estimate = Column(Boolean, nullable=False, default=False)
# ์ค์
revenue = Column(Float) # ๋งค์ถ์ก (์ต์)
op_income = Column(Float) # ์์
์ด์ต (์ต์)
net_income = Column(Float) # ๋น๊ธฐ์์ด์ต (์ต์) โ ํ์ ๋ง
# ์ฃผ๋น ์งํ
eps = Column(Float) # EPS (์)
bps = Column(Float) # BPS (์)
dividend_per_share = Column(Float) # ์ฃผ๋น๋ฐฐ๋น๊ธ (์)
dividend_yield = Column(Float) # ๋ฐฐ๋น์์ต๋ฅ (%)
# ์ฌ๋ฌด์ํ
equity = Column(Float) # ์๋ณธ์ด๊ณ (์ต์)
total_assets = Column(Float) # ์์ฐ์ด๊ณ (์ต์)
shares_outstanding = Column(Float)
# ์์ ์ฑ ๋น์จ โ ํ์ ์ฐ๋๋ง (์ถ์ ์ฐ๋๋ NULL)
roe = Column(Float) # ROE (%)
roa = Column(Float) # ROA (%)
debt_ratio = Column(Float) # ๋ถ์ฑ๋น์จ (%)
interest_bearing_debt = Column(Float) # ์ด์๋ฐ์๋ถ์ฑ (์ต์)
# ๋ฉํ
is_stale = Column(Boolean, default=False)
updated_at = Column(DateTime)
__table_args__ = (
Index("ix_annual_data_ticker_year_is_estimate", "ticker", "year", "is_estimate"),
Index("ix_annual_data_ticker_is_estimate", "ticker", "is_estimate"),
)
class User(Base):
"""Google OAuth ๋ก๊ทธ์ธ ์ฌ์ฉ์."""
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
google_id = Column(String, unique=True, nullable=False)
email = Column(String, nullable=False)
name = Column(String)
is_admin = Column(Boolean, default=False)
created_at = Column(DateTime, default=lambda: datetime.utcnow() + timedelta(hours=9))
class Watchlist(Base):
"""๊ด์ฌ์ข
๋ชฉ. ์ฌ์ฉ์๋ณ ๊ฒฉ๋ฆฌ."""
__tablename__ = "watchlist"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
ticker = Column(String, ForeignKey("company.ticker"), nullable=False)
added_at = Column(DateTime, default=lambda: datetime.utcnow() + timedelta(hours=9))
memo = Column(String, default="")
__table_args__ = (UniqueConstraint("user_id", "ticker"),)
class BondRate(Base):
"""๊ตญ์ฑ 10๋
๋ฌผ ๊ธ๋ฆฌ. ๋จ์ผ row (id=1) upsert."""
__tablename__ = "bond_rate"
id = Column(Integer, primary_key=True, default=1)
rate = Column(Float, nullable=False) # % (์: 3.2)
fetched_at = Column(DateTime)
class Feedback(Base):
"""์ฌ์ฉ์ ํผ๋๋ฐฑ/๋๊ธ."""
__tablename__ = "feedback"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
content = Column(String, nullable=False)
created_at = Column(DateTime, default=lambda: datetime.utcnow() + timedelta(hours=9))
|