포트폴리오의 리밸런스: 효과를 계산해 보았다(리밸런스편)

이전 기사에서는 주가 정보를 가져오는 곳까지 소개했습니다.

목차


  • 포트폴리오의 리밸런스: 효과를 계산해 보았다(주가 취득편)
  • 포트폴리오의 리밸런스 : 효과를 계산해 보았다 (리밸런스 편) (본 기사)

  • 2. 리밸런스편



    여기에서는 실제로 리밸런스의 효과를 확인하기 위해서 세금·수수료의 약간 까다로운 곳도
    싹둑 모델화해 계산해 보겠습니다.

    2.1 우선 결과로부터



    코드가 흩어져 버렸기 때문에 함수(getHistoricalMarketValue.m)는 모아 마지막에 소개합니다만,
    targetWeight = [31, 23.4, 6.1, 27.7, 6.8, 5.0]/100;
    commission = 0.0054; % 取引手数料(税込み) 0.54%
    taxrate = 0.20; % 税金はざっくり 20%
    rebalanceThreshold = 0; % 毎週
    
    % pfQty  保有数
    % pfMarketValue  評価額
    [pfMarketValue, pfQty] = getHistoricalMarketValue(pricedata, divdata, ...
                                                      commission, taxrate, ...
                                                      rebalanceThreshold, targetWeight);
    

    느낌으로 계산합니다. 우선 타겟의 종목 비율, 수수료율, 세율을 지정. rebalanceThreshold는 균형이 얼마나 깨졌을 때 재조정을 수행할지에 대한 임계값을 지정합니다. 0%의 경우는 매주(주간 데이터이므로) 리밸런스를 실시하고, 100%의 경우는 리밸런스는 실시되지 않습니다.

    얻은 결과를 시각화합니다.
    figure
    subplot(2,1,1)
    bar(pricedata.time,pfMarketValue,'stacked','DisplayName','tmp');
    legend(pricedata.Properties.VariableNames)
    title('評価額推移(リバランスあり)')
    
    subplot(2,1,2)
    ps = pfMarketValue./sum(pfMarketValue,2);
    bar(pricedata.time,ps,'stacked','DisplayName','tmp');
    title('各銘柄の保有割合の推移(リバランスあり)')
    



    플롯 해 보면 깨끗하게 리밸런스 되어 있는 것을 알 수 있군요.

    참고까지, 리밸런스하지 않았던 경우(+76%)도 플롯 해 둡니다.
    rebalanceThreshold = 1; % リバランス無しに設定
    [pfMarketValue, pfQty] = getHistoricalMarketValue(pricedata, divdata, ...
                                                      commission, taxrate, ...
                                                      rebalanceThreshold, targetWeight);
    figure
    subplot(2,1,1)
    bar(pricedata.time,pfMarketValue,'stacked','DisplayName','tmp');
    legend(pricedata.Properties.VariableNames)
    title('評価額推移(リバランス無し)')
    
    subplot(2,1,2)
    ps = pfMarketValue./sum(pfMarketValue,2);
    bar(pricedata.time,ps,'stacked','DisplayName','tmp');
    title('各銘柄の保有割合の推移(リバランス無し)')
    



    주가가 크게 떨어진 리먼 쇼크당 채권(AGG) 비율이 훨씬 높아졌습니다. 채권의 비율이 커져 버린 것으로, 그 후의 주가의 성장을 누릴 수 없었다··라고 느끼겠습니까.

    리밸런스는 하면서, 수수료로 지나치게 지워지지 않도록, 크게 시세가 움직일 때만 리밸런스를 한다, 그런 경우를 상정해 15% 무너졌을 때만 리밸런스를 실시하는 케이스를 플롯한 것이 이하. 2회 리밸런스가 발생하고 있네요. 결과적으로 재조정하지 않을 때에 비해 24% (+76% -> +100%) 성능이 향상되었습니다.



    주가는 계속 오르고 있었기 때문에 2번째의 리밸런스는 실시하지 않는 것이 퍼포먼스는 좋았을지도 모르겠네요.

    아니, 원래 리밸런스는 「리밸런스에 의해서, 리스크를 너무 취하는 것을 막는」것이 목적이었습니다.

    2.2 getHistoricalMarketValue.m



    실제의 리밸런스를 실시하고 있는 코드는 이쪽. 수수료・세금의 취급이 귀찮습니다.
    괴로워 혼란에 여러가지 눈을 찌르고 코드화하고 있습니다만, 치명적인 실수가 있으면 가르쳐 주세요. .

    getHistoricalMarketValue.m
    function [pfMarketValue,pfQty,fees,taxes] = getHistoricalMarketValue(pricedata, divdata, ...
                                                                         commission, taxrate, ...
                                                                         rebalanceTh, targetWeight)
    
    
    pfQty = zeros(size(pricedata)); % 保有数
    pfMarketValue = zeros(size(pricedata)); % 評価額
    fees = zeros(height(pricedata)); % 手数料
    taxes = zeros(height(pricedata)); % 税金
    
    pfQty(1,:) = pricedata{1,:}.\targetWeight; % 初期保有数
    pfMarketValue(1,:) = pricedata{1,:}.*pfQty(1,:); % 初期評価額
    
    % 2週目から順に計算
    for ii=2:height(pricedata)
    
        pfQty_old = pfQty(ii-1,:);
    
        % 先週と同じ株数での評価額
        % 配当金も再投資しますが購入手数料と税金は引いておきます。
        pfMarketValue(ii,:) = (pricedata{ii,:}+divdata{ii,:}*(1-commission)*(1-taxrate)).*pfQty_old;
        % 配当金再投資後の株数
        pfQty(ii,:) = pfMarketValue(ii,:)./pricedata{ii,:};
    
        % 現時点での評価額
        MarketValueNow = sum(pfMarketValue(ii,:),2);
        % ポートフォリオバランス確認
        actualWeight = pfMarketValue(ii,:)/MarketValueNow;
        % ターゲットとの差分
        difWeight = actualWeight - targetWeight;
    
        % 1銘柄でも最低閾値を超えてバランスが崩れていればリバランス実行
        if max(abs(difWeight)) > rebalanceTh
    
            what2sell = difWeight > 0; % 想定割合を超えている銘柄認識
            amount2sell = difWeight(what2sell)*MarketValueNow; % 各銘柄の売却額
    
            % 売却益はあるかな?(簡易的に初期購入時の株価との差額を使用)
            priceDif = pricedata{ii,what2sell} - pricedata{1,what2sell}; % 株価の差額(1株当たり)
            capGain = priceDif.*(amount2sell./pricedata{ii,what2sell}); % 差額 x 売却株数 = 売却益
            capGain = capGain - sum(amount2sell)*commission; % 手数料分減額
    
            % 売却益 x 20% は税金(マイナスの場合還付あり想定)
            taxLoss = sum(capGain)*taxrate;
    
            % 手数料も引いて購入資金となる・・と。(売却・購入双方)
            totalLoss = sum(amount2sell)*commission*2 + taxLoss;
            % 税引き後の評価額
            pfQty(ii,:) = pricedata{ii,:}.\targetWeight*sum(MarketValueNow - totalLoss);
    
            pfMarketValue(ii,:) = pfQty(ii,:).*pricedata{ii,:};
    
            taxes(ii) = taxLoss;
            fees(ii) = sum(amount2sell)*commission*2;
        end
    end
    end
    

    좋은 웹페이지 즐겨찾기