Lindo Systems

! Do parametric analysis of Portfolio variance vs. expected return
  for a Markowitz portfolio model in LINGO (PortEfFrontxx.lng).
! Different cases can be run by turning on or off statements
  of the form: !CaseXX;
! Keywords: Parametric Analysis, Markowitz, Graph, Chart, Chartcurve
    Pareto analysis, Efficient frontier, Portfolio;
      SETS:
       ASSET: STD, X, STDPP, EXPNS, TAXR, ERET;
       TMAT( ASSET, ASSET) | &1 #GE# &2: CORR;
       GRID: VINP, VOUT;
      ENDSETS

      DATA:
! Case based on Vanguard Fund data;
    ! The initial wealth;
!CaseVG   WEALTH = 1;

 ! The investments available(Vanguard funds), and their expected
     return per year, i.e., expected value next year is (1 + ERET(i));
!CaseVG   ASSET = CD___   VG040   VG102   VG058   VG079    VG072    VG533;
!CaseVG   ERET = .04     .06     .06     .05     .065      .07      .08   ;
   ! S.D. per period (monthly here) in return for each asset, June 2004 to Dec 2005;
!CaseVG   STDPP=   0   .02341   .02630   .01067  .02916    .03615   .05002;

    ! Correlation matrix, based on June 2004 to Dec 2005;
!CaseVG   CORR =
         1
         0       1    	
         0    .98209      1    	
         0   -.24279  -.31701       1   
         0    .75201   .76143   -.34311      1
         0    .49386   .49534   -.24055  .68488     1
         0    .77011   .76554   -.18415  .84397  .69629     1;
      ! Number different returns to check;
!CaseVG   NPERYR = 12;  ! Number observation periods per year;
!CaseVG   NPOINTS = 17;
!CaseVG   GRID = 1..NPOINTS;

! Case based on data from Harry Markowitz;
! The initial wealth;
!CaseHM WEALTH = 1;
 ! The investments available, and their expected
     return per year, i.e., expected value next year is (1 + ERET(i));
!CaseHM  ASSET =  ATT        GMC       USX;
!CaseHM  ERET = 1.0890833  1.213667  1.234583;
   ! S.D. per period (yearly here) in return for each asset, 1943 to 1954;
!CaseHM  STDPP= 0.103959   0.241644 0.306964;

! Correlation matrix, based on 1943 to 1954;
!CaseHM    CORR =
                 1
                0.493895589  1    	
                0.409727718  0.747229121   1 ;
!CaseHM   NPERYR = 1;  ! Number observation periods per year;
! Number different returns to check;
!CaseHM   NPOINTS = 17;
!CaseHM   GRID = 1..NPOINTS;

! Case HM + T bills;
! The initial wealth;
!CaseTbill   WEALTH = 1;
 ! The investments available, and their expected
     return per year, i.e., expected value next year is (1 + ERET(i));
!CaseTbill  ASSET =  ATT        GMC       USX      TBILL;
!CaseTbill  ERET = 1.0890833  1.213667  1.234583    1.03;
   ! S.D. per period (yearly here) in return for each asset, 1943 to 1954;
!CaseTbill  STDPP= 0.103959   0.241644 0.306964      0;

! Correlation matrix, based on 1943 to 1954;
!CaseTbill    CORR =
                 1
                0.493895589  1    	
                0.409727718  0.747229121   1 
                0            0             0       1;
!CaseTbill   NPERYR = 1;  ! Number observation periods per year;
! Number different returns to check;
!CaseTbill   NPOINTS = 17;
!CaseTbill   GRID = 1..NPOINTS;

! Case on some stocks from 1975 to 2017;
! The initial wealth;
!Case7517;  WEALTH = 1;
 ! The investments available, and their expected
     return per year, i.e., expected value next year is (1 + ERET(i));
!!!Note, this dataset does not include dividends;
!Case7517; ASSET =
         3M    CHEVRON   COCACOLA     DUPONT      PANDG        IBM WEYERHAUS        FORD         GE  ALCOARNC   EXXONMOBL      DEERE     BOEING      MERCK    CD;
!Case7517; ERET = 
   0.104840   0.110333   0.129940   0.089581   0.099156   0.097740   0.062126   0.148514   0.111147   0.113428   0.102323   0.138958   0.221723   0.117267   0.04;

   ! S.D. per period (yearly here) in return for each asset;
!Case7517;  STDPP=
   0.179183   0.199911   0.227568   0.204611   0.166706   0.271494   0.216099   0.630138   0.252424   0.331500   0.160082   0.314638   0.388914   0.278148     0;

! Correlation matrix;
!Case7517;   CORR =
   1.000000
   0.224103   1.000000
   0.471504   0.188059   1.000000
   0.569111   0.369613   0.540056   1.000000
   0.383458   0.159070   0.605610   0.451472   1.000000
   0.177980   0.195755   0.185002   0.218867   0.299420   1.000000
   0.536024   0.307412   0.288499   0.492221   0.304817   0.202478   1.000000
   0.436319  -0.029829   0.298691   0.421983   0.163719   0.427427   0.495507   1.000000
   0.375731   0.335635   0.508517   0.504409   0.558811   0.425427   0.526197   0.282949   1.000000
   0.589535   0.288138   0.150212   0.521401   0.316703   0.283604   0.613098   0.340376   0.406583   1.000000
   0.137225   0.693282   0.326282   0.335877   0.188402   0.208952   0.264360  -0.098702   0.487905   0.169956   1.000000
   0.397611   0.469478   0.204834   0.435663   0.176196   0.117376   0.402432   0.258821   0.188560   0.502105   0.293903   1.000000
   0.526127   0.353309   0.320309   0.351982   0.080585   0.107582   0.145074   0.106664   0.192651   0.267838   0.269439   0.354856   1.000000
   0.326960   0.195902   0.648996   0.385934   0.279656   0.048635   0.185938   0.084664   0.359242   0.104470   0.461664   0.166394   0.181214   1.000000 
   0          0          0          0          0          0          0          0          0          0          0          0          0          0          1;
!Case7517;  NPERYR = 1;  ! Number observation periods per year;
! Number different returns to check;
!Case7517;  NPOINTS = 17;
!Case7517;  GRID = 1..NPOINTS;
     ENDDATA
    !--------------------------------------------------------------;
     SUBMODEL HARRY:
    !  Min the var in yearly portfolio return;
      [OBJ] MIN = (@SUM( ASSET( I): STD( I)*STD(I) * X( I)^2) +
             2 * @SUM( TMAT( I, J) | I #NE# J:
              X( I) * X( J)* CORR( I, J) *( STD( I) * STD( J)))) ;
    !  Budget constraint;
       [BUDGET] @SUM( ASSET(i): X(i)) = WEALTH;
    !  Return requirement;
       [RETURN] @SUM( ASSET(i): ERET(i) * X(i)) >= TARGET * WEALTH;
      ENDSUBMODEL

     CALC:
! Set various performance parameters;
      @SET( 'TERSEO',2);    ! Output level (0:verb, 1:terse, 2:only errors, 3:none);
      @SET( 'IPTOLR', .02); ! Set ending relative optimality tolerance;
      @SET( 'TIM2RL', 10);   ! Time in seconds to apply optimality tolerance;
      @SET( 'DUALCO', 1);   ! Set dual computations  (0:off, 1:On);
      @SET( 'OROUTE',1);   ! Route output immediately to the window line by line;
      @SET( 'GLOBAL',0);   ! 0:Do not use Global solver, 1:Use the Globasolver;
      @SET( 'TATSLV', 150); ! Solver time limit in seconds (0:no limit) for @SOLVE's;
      @SET( 'TIMLIM', 5);   ! Solver time limit in seconds (0:no limit) for entire session;
      @SET( 'LINLEN', 85); !  Terminal page width (0:none);
      @SET( 'USEQPR', 1);  ! Use quadratic recognition (1:y, 0:n);

       ! Compute effective variances and returns;
       @FOR( ASSET(I): 
       ! Assume variances add over time to compute yearly std. dev.;
          STD(I) = STDPP(I)*(NPERYR^.5);
            );
       ! Find min and max return;
          RET_MIN = @MIN( ASSET(I): ERET(I));
          RET_MAX = @MAX( ASSET(I): ERET(I));
       ! Prepare heading for little report;
       @WRITE(@NEWLINE(1),' Efficient Frontier Portfolio Calculation',@NEWLINE(1));
       @WRITE(' Target  Risk(1 sd)   Portfolio composition',@NEWLINE(1));
       @WRITE(' Return    1-Yr ');

       @FOR( ASSET(I):
         @WRITE(@FORMAT(ASSET(i),'10s'));
           );
       @WRITE( @NEWLINE(1));
       N1 = NPOINTS-1;
       K = 0; 
       ! Loop over different target returns, i.e., we change the
         value of TARGET in each pass through the loop;
       ! Use integer count to avoid accumulating roundoff;
       @WHILE( K #LT# NPOINTS:
         TARGET = RET_MAX*(K/N1) + RET_MIN*((N1-K)/N1);
         @SOLVE( HARRY);
         RISK = OBJ;
         SDP = RISK^0.5; ! Standard deviation of portfolio return;
         @WRITE( ' ',@FORMAT( TARGET, '#6.5f'),' ');
         @WRITE( @FORMAT( SDP, '#7.4f'),' ');
         @FOR( ASSET(I):
           @IFC( X(i) #GT# .0001:
             @WRITE( @FORMAT( X(i), '10.4f'));
            @ELSE
             @WRITE('          ');
               )
              );
         @WRITE( @NEWLINE(1));
         K = K + 1;
        ! Store the input and output variables for graphing;
         VINP( K) = TARGET;
         VOUT( K) = SDP;
             ); ! While end;

         @WRITE( @NEWLINE(1),'  Input Data Used:', @NEWLINE(1));
         @WRITE('Expected ret/yr:');
         @FOR( ASSET(I):
           @WRITE( @FORMAT( ERET(i), '10.4f'));
              );
         @WRITE( @NEWLINE(1));
         @WRITE('Stdev in ret/yr:');
         @FOR( ASSET(I):
           @WRITE( @FORMAT( STD(i), '10.4f'));
              );
      ! Graph it;
        @CHARTCURVE( 'Risk vs Return', 'Desired Return', 'Resulting Risk (SD)', 'Standard Deviation', VINP, VOUT);
      ! Graph it as is done by Finance folks;
        @CHARTCURVE( 'Return vs Risk', 'Standard Deviation in Return', 'Expected Return', 'Standard Deviation', VOUT, VINP);
     ENDCALC