}

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [데이터 분석] 행위자 기반 모형 (Agent Based Model) [긴 버전]
    Data Science/데이터 분석, ML 2023. 8. 15. 23:06
    반응형


     

    1. 들어가는 글

    몬테 카를로 시뮬레이션에 대해 쓰면서 잠깐 말했지만,

    시뮬레이션을 하는 방법 중에 행위자 기반 모형이라는 게 있습니다.

    처음 이걸 접할 때가 아마 대학원 첫 학기로 기억해요.

    당시에는 아직 연구주제를 명확하게 정하던 때가 아니라 이것저것 관심을 갖고 있었어요.

    특히 학부에서는 잘 다루지 않았던 행동경제학은 게임이론과 더불어 경제학도라면 관심가질 만한 분야일거에요.

    때마침 한 선배가 행동경제학에서 주로 하는 시뮬레이션을 학습하는 모임을 추천해주셔서 참여한 적이 있어요.

    Netlogo를 활용했는데, 처음엔 나비모형이라는 걸 배웠습니다.

    나비모형이라고 하니까 왠지 나비효과 같은 걸 생각했는데 그런 건 아니었어요.

    단순히 나비가 펄럭펄럭 날아서 산까지 날아가는 걸 만들어 보는 거 였습니다.

    그 다음에 만든 모형은 사람들이 시장에 장보러 가는 걸 만들었던 것 같네요.

     

    당시에는 컴퓨터 안에서 만드는 세상이라는 게 크게 매력적으로 다가오지는 않았던 것 같습니다.

    세상에 차고 넘치는 데이터를 보고, 숨겨진 원리를 찾는 일이 더 재밌었던 것 같아요.

    그러다가 졸업 논문을 쓸 때, 훨씬 복잡한 모형을 다루는 논문을 본 적이 있었어요.

    참 인상깊었는데, 생각보다 다양한 분야에서 쓰이는 게 바로 행위자 기반 모형이더라구요.

     

    왜 많이 쓰이느냐.

    묻는다면 아마 이론적인 기반을 갖추면서도 유연하기 때문일거에요.

    이론을 충실히 만족한 현상을 관측하는 건, 상당히 어렵거든요.

    예를 들어 대학원 거시경제학에서 배우는 중에 무한기간모형(Infinite horizon model)이라고 있어요. 

    이름이 왜 무한기간이냐면, 개인이 죽지 않는다고 가정하거든요(...).

    개인이 죽지 않으니, 효용함수가 시간에 따라 달라지지 않는다는 장점이 있는 모형입니다.

     

    굉장히 긴 시간, 경제학 용어로 '장기적으로' 볼 때에는 이론이 정당화되기는 합니다.

    한 개인이 죽기 전에 자손을 낳고, 자손도 다시 자신의 자손을 낳을테니까요.

    하지만 무한히 사는 개인을 대상으로 하는 현상을 직접 관측하는 건 불가능합니다.

     

    이럴 때엔, 모형의 가정을 충족하는 시뮬레이션을 해볼 수 있습니다.

    그리고 시뮬레이션의 결과에서 중요한 인사이트를 찾아보는 거죠.

     

     

     


     

     

    2. 행위자 기반 모형(Agent Based Model)이란?

    ※ 아래 글은 조남운 박사님의 논문을 참고하여 작성했습니다.

    위키백과에 따르면 행위자 기반 모형은 복잡한 거시현상을 미시적 행위자의 상호작용으로 설명하기 위해 제안된 모형이에요. 학술적인 표현을 빌리자면, 미시적 토대로부터 거시적 패턴(emergent marco pattern)을 분석하기 위한 시뮬레이션 계산 모형입니다.

     

    말은 어렵지만, 중요한 건 미시적인 영역으로부터 거시적인 영역을 설명하고자 하는 모형을 말합니다.

    미시적인 영역라고 한다면 사회 또는 자연을 이루는 작은 분석 단위를 말해요.

    예를 들어 경제학에서의 작은 분석 단위라고 하면 개인, 기업 등이 있어요.

    거시적인 영역이라고 하면 사회 또는 자연현상 그 자체는 말하는 경우가 많습니다.

    대표적으로 주식시장, 국민경제, 국제무역 같은 것이 될 수 있겠네요.

    종합해보면 개인과 개인, 기업과 기업 또는 개인과 기업 간에 발생하는 다양한 상호작용이,

    주식시장, 국민경제, 국제무역 등에 어떤 영향을 미치는지 보고자 할 때 사용됩니다.

     

    당연히 미시영역이나 거시영역은 정의하기 나름일 거에요.

    국가간에 상호작용이 국제 경제나 정치에 미치는 영향을 설명하거나,

    원자 간의 상호작용이 여러 물질간의 결합에 어떤 영향을 미치는지 설명할 때도 사용할 수 있습니다.

     

    행위자 기반 모형이라고 부르는 이유는, 미시영역에 해당하는 '행위자'를 상정하기 때문이에요.

    행위자에 대해서 여러 가지 가정을 해요. 

    예를 들어 개인은 자신의 효용을 극대화한다거나, 소득에서 일부는 소비를 한다는 식의 가정을 합니다.

    그 뒤에 여러 상황을 줍니다.

    물가가 오른다거나, 소득이 늘어난다거나 하는 식으로요.

    그 때 행위자가 어떤 행동을 하는지, 그리고 그 총합인 거시현상에서는 어떤 일이 벌어지는지를 보는 거죠.

     

    행위자 기반 모형은 주로 Netlogo라는 언어를 활용합니다.

    Netlogo에는 이미 다양한 모형들이 있거든요.

    그래서 자신이 원하는 상황과 유사한 기존 모형을 적절히 수정하면 빠른 시일 내에 결과를 낼 수 있어요.

     

    하지만 저는 Netlogo를 어설프게 배웠고, 포스트 쓰자고 다시 배울 열정도 없어요(...).

    그러므로, 파이썬으로 구현해보겠습니다.

     

     


     

     

    3. 위험자산의 변동성이 커지면, 사람들은 안전자산(예금)을 많이 가입할까?

    시뮬레이션을 해보기 위해 아래와 같은 상황을 가정해보겠습니다.

    실제 현실은 매우 복잡하겠지만, 우선은 구현하는 걸 보이는 게 목표니까 최대한 간결한 가정만 하겠습니다.

     

     

    (1) 개인

    개인은 자신의 효용, 정확히는 수익을 극대화하고자 한다고 하겠습니다.

    또한 개인은 효율적인 포트폴리오를 구성하고자 합니다.

    이 때 사람마다 투자를 통해 감내할 수 있는 리스크 $\sigma_{i}$는 천차만별입니다.

    어떤 사람은 충분히 많은 리스크를 감내하고, 또 다른 사람은 리스크 자체를 싫어할 수도 있으니까요.

    편리하게, 사람에 따른 최대 리스크 한도는 균등분포를 따른다고 하겠습니다.

     

    $$ \begin{align} \sigma_{i} \sim Uniform(0, \sigma_M) \end{align} \tag{1} $$

     

    그리고 이 최대 리스크 한도는 시간이 흘러도 변하지 않는다고 하겠습니다.

     

    (2) 자산

    자산은 위험자산(=주식)과 무위험자산(=채권 또는 예금)만 존재한다고 하겠습니다.

    무위험자산의 리스크는 0이고, 위험자산과 무위험자산은 상관관계가 없습니다.

    따라서 포트폴리오의 리스크 $\sigma_p$는 위험자산에 대한 투자비중 $w_{risk}$와 위험자산의 리스크 $\sigma_{risk}$의 곱과 같습니다.

     

    $$ \begin{align} \sigma_p = w_{risk} * \sigma_{risk} \end{align} \tag{2} $$

     

     

    (3) 투자하는 방식

    개인마다 최대 리스크 한도는 다르다고 했습니다.

    한편 개인은 수익을 극대화하는 존재이므로, 자신이 허용할 수 있는 최대 리스크 한도까지 포트폴리오를 구성할 겁니다.

    즉 개인마다 구성하게 되는 포트폴리오는 최대 리스크 한도와 같습니다.

    따라서 위험자산에 대한 투자비중은 최대 리스크 한도 $\sigma_i$를 위험자산의 리스크 $\sigma_{risk}$로 나눈 값입니다.

    $$ \begin{align} \sigma_i = & \sigma_p = w_{risk} * \sigma_{risk} \\[15pt] \Leftrightarrow & \; w_{risk} = \frac{\sigma_i}{\sigma_{risk}} \tag{3} \end{align} $$

     

    그리고 개인은 매기마다 리밸런싱을 할겁니다.

    쉽게 말하면 연초에 투자를 하고, 연말에 정산한다고 생각하면 됩니다.

    예를 들어 여러분이 2022년 1월 1일에 자산 100만원을 투자한다고 해보겠습니다.

    주식은 수익률이 10%, 예금은 5%라고 해볼게요.

    이 때 리스크 한도를 감안해서, 주식에 40% 예금에 60%를 투자할겁니다.

    그러면 2022년 12월 31일이 되면 107만원이 됩니다.

    (주식투자 40만원 → 수익 4만원, 예금투자 60만원 → 수익 3만원)

    2023년 1월 1일이 되면 여러분은 107만원을 다시 투자합니다.

    다시 40%를 주식에, 60%를 예금에 투자합니다.

    그러면 2023년 12월 31일에는 114.49만원을 손에 쥐게 될겁니다.

     

    이걸 다양한 리스크 한도를 지닌 무수히 많은 사람들을 대상으로,

    무한히 긴 시간동안 시뮬레이션할 겁니다.

    시뮬레이션 실행코드는 더보기를 참고하시기 바랍니다.

    앞선 설명에 없지만, 나중에 더 작업하려고 만들어둔 Economy 클래스 같은 것들은 무시하셔도 좋습니다.

    더보기
    import random
    import pandas as pd
    
    class Economy :
    
        def __init__(self):
            pass
    
        @classmethod
        def setDefault(cls):
            # Economic circumstance setup
            pass
    
    class Individual:
    
        def __init__(self):
            # 개인의 고유 특성
            self.income = random.randint(50, 100)
            self.risk_tolerance = random.uniform(0, 0.05)
    
            # 포트폴리오
            self.weight_risky = 0       # 위험자산에 대한 투자비중
            self.weight_safe = 0        # 안전자산에 대한 투자비중
            self.amount_risky = 0       # 위험자산 투자금액
            self.amount_safe = 0        # 안전자산 투자금액
    
            self.portfolio_risk = 0     # 개인 포트폴리오 리스크
            self.portfolio_return = 0   # 개인 포트폴리오 수익
    
        def ConstructPortfolio(self, Equity_risk, Equity_return, Bond_risk, Bond_return):
            self.weight_risky = min(1, self.risk_tolerance/Equity_risk)
            self.weight_safe = 1 - self.weight_risky
    
            self.amount_risky = self.weight_risky * self.income
            self.amount_safe = self.weight_safe * self.income
    
            self.portfolio_return = self.weight_risky * Equity_return + self.weight_safe * Bond_return
            self.portfolio_risk = self.weight_risky * Equity_risk + self.weight_safe * Bond_risk
    
    
    class Bank :
    
        def __init__(self):
            # initiating
            pass
    
        def Finance_fund(self, deposit):
            # Do finance
            pass
    
    
    class Asset :
    
        def __init__(self):
            pass
    
    class Equity(Asset) :
    
        def __init__(self, risk = None, R = None):
            super().__init__()
            if risk is not None : self.risk = risk
            if R is not None : self.R = R
    
    class Bond(Asset) :
    
        def __init__(self, risk = None, R = None):
            super().__init__()
            if risk is not None : self.risk = risk
            if R is not None : self.R = R
    
    
    
    if __name__ == '__main__' :
    
        data = pd.DataFrame([], columns=['Deposit', 'Profit', 'Income'])
    
        # 개인 생성
        N = 100  # 인구수
        T = 100  # 기간
    
        random.seed(42)
        individuals = {}
        for i in range(1, N + 1):
            individuals[i] = Individual()
    
        # 은행 생성
        BK = Bank()
    
        # 시뮬레이션 실행
        for t in range(1, T + 1):
    
            # 시장상황 Setting
            Economy.setDefault(inflation=0.02, basemoney_rate=0.01)
    
            # 자산 생성 (주식 : 기대수익률 6%, 리스크 40% / 채권 : 기대수익률 2%, 리스크 0)
            E = Equity(risk=0.40, R=0.06)
            B = Bond(risk=0.00, R=0.02)
    
            # (기초) 개인 포트폴리오 구성
            deposit = 0  # 총 예수금 (기초)
            income = 0  # 총 소득   (기초)
            for i in range(1, N + 1):
                individuals[i].ConstructPortfolio(Equity_risk=E.risk, Equity_return=E.R,
                                                  Bond_risk=B.risk, Bond_return=B.R)
                deposit += individuals[i].amount_safe
                income += individuals[i].income
    
            # 은행의 자금운용
            BK.Finance_fund(deposit)
    
            # (기말) 개인 수익 정산 (= 포트폴리오 기대수익만큼 상승)
            for i in range(1, N + 1):
                individuals[i].income = (1 + individuals[i].portfolio_return) * individuals[i].income
    
            data.loc[t, 'Deposit'] = deposit
            data.loc[t, 'Profit'] = BK.profitAmount
            data.loc[t, 'Income'] = income
    
        # 개인에 대한 상세내역
        a = [i.risk_tolerance for i in individuals.values()]
        b = [i.weight_safe for i in individuals.values()]
        c = [i.weight_risky for i in individuals.values()]
    
        individualsDetails = pd.DataFrame([a, b, c], index=['Tol', 'W_safe', 'W_risky']).T

     


     

     

    4. 시뮬레이션 결과

    편의를 위해 사람은 100명, 기간도 100기까지만 설정했습니다.

    그리고 맨 처음에 투자할 돈이 있어야 시작을 할텐데요,

    초기 금액도 역시 균등분포를 사용해서 임의로 분배했습니다.

    제 경우는 주식의 리스크($\sigma_{risk}$)를 키워가면서 시뮬레이션을 해봤는데요,

    주요 시사점은 이렇습니다.

     

    (1) 우선 위험자산의 리스크가 커지면 사람들이 주식에 투자하는 비중을 줄이는 건 사실입니다.

    식(3)을 보더라도 자명하지요. 위험자산의 리스크가 커지면 분모가 커지는 꼴이니, 투자비중은 줄기 마련입니다.

     

    (2) 하지만 장기적으로 안전자산에 투자한 총 금액은 많이 늘지 못합니다.

    위험자산의 리스크가 커질수록, 안전자산에 투자하는 비중은 줄어든다고 했습니다.

    하지만 장기적으로는 안전자산에 투자하는 금액이 크게 성장하지 못해요.

     

    예를 들어 볼게요.

    위험자산의 리스크가 낮은 경우와 큰 경우를 비교해보겠습니다.

    처음에는 위험자산의 리스크가 큰 경우에 안전자산에 투자한 금액이 훨씬 더 많습니다.

    충분히 상식적이지요.

    위험자산의 리스크가 큰 경우 안전자산에 대한 선호도가 높아질테니까요.

     

    하지만 이 상태로 50년, 100년이 지나면 어떻게 될까요?

    결과는 반대가 됩니다.

    위험자산의 리스크가 작은 경우, 즉 상대적으로 안전자산에 대한 선호도가 더 작은 경우에 안전자산에 투자한 금액이 훨씬 더 많아집니다.

     

    왜 그럴까요?

    위험자산에 많이 투자할수록, 개인의 '총 자산'은 더 커져요.

    즉 파이 자체가 커진 셈입니다.

    그래서 안전자산에 투자하는 비중이 상대적으로 적어도(=위험자산에 많이 투자하더라도),

    안전자산에 투자하는 금액 자체는 더 커지게 되는 겁니다.

     

    따라서 대표적인 안전자산을 취급하는 은행의 입장에서

    단순히 위험자산의 변동성이 커진다, 안전자산에 대한 선호가 늘어난다고 좋아할 문제는 아닙니다.

    중요한 건 '고객의 자산' 자체가 커지는 게 중요하죠.

    '고객의 자산' 자체가 커지면, 장기적으로는 예수금 성장이 더 커질테니까요.

     

     


     

    반응형

    댓글

Designed by Tistory.