⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emhftrader.m

📁 仿真人工金融市场Jackson代码
💻 M
字号:
//  EMHFTrader.m//  This file defines the method of stock valuation for//  fundamental traders who believe the markets are efficient....//  An implication of this belief is that they expect the //  price to be correct in the coming period and all that follow.//  Hence, they derive their expected return by calculating the//  fundamental value and the expected fundamental value in the//  future.//#import "EMHFTrader.h"// Implementation of a EMH fundamental trader ..@implementation EMHFTrader-createEnd {   // ensure all distributions are initialized   [super createEnd];   // This is a quarterly rate, can override 2.5% default from Trader    //   discountRate = 0.10;   //  let them start out well   expRiskyCFLag = [mktStats getEarningsLag: 0];   // for use in determining demand schedule each period   dmdList = [List create: [self getZone]];   supList = [List create: [self getZone]];   [self projectEarnings];return self;}-printEstimates {   if (diagLevel & TRADER_STRATEGY) {     printf ("<%s> in (%d) days, expEarnings (%f), priorEarnings (%f) \n",                [self getName],                daysTillEarnings,                risky1CF,                expRiskyCFLag );   }   return self;}-projectEarnings {   double rho;   if (diagLevel & METHOD_ENTRY)     printf("*** projectEarnings (EMHFTrader) \n");   // Determine expected 1-period ahead price and periodic cash flow   // Use rational expectations forecast.   //  If CF follows ARMA(1,1) process as described in paper,   //    rational expectations forecast of next CF is weighted   //    avg of last CF and last forecast CF   rho = 1+riskyGrowthRate;   riskyCF = [mktStats getEarningsLag:0];   // for initial forecast   if (expRiskyCFLag == 0)     expRiskyCFLag = riskyCF;   correctCFEst = 0.75 * expRiskyCFLag +                (rho - 0.75) * riskyCF;   // for those who estimate with a bias   risky1CF = correctCFEst + (correctCFEst*[self getBias]);   // save forecast for next time   expRiskyCFLag = risky1CF;   if (diagLevel & TRADER_STRATEGY)     [self printEstimates];return self;}-(double) getBias {  return (0);}-updateProjections {  if (diagLevel & TRADER_STRATEGY)    [self printEstimates];  // This trader does not update projections based on bogus information.  return self;}-printValue {   if (diagLevel & TRADER_STRATEGY)     printf ("   values risky at (%f) and P1 (%f) with (%d) til earnings.\n",                riskyValue, expP1, daysTillEarnings);   return self;}-calcSchedule {  double dmdTotal;  id index;  ShareRequest * aRequest;#if 0  [self calcShrsDemand: (riskyValue)*(1-0.15)];  [self calcShrsDemand: (riskyValue)*(1-0.10)];  [self calcShrsDemand: (riskyValue)*(1-0.050)];#endif  [self calcShrsDemand: (riskyValue)*(1-0.020)];  [self calcShrsDemand: (riskyValue)*(1-0.010)];  [self calcShrsDemand: (riskyValue)*(1-0.005)];  [self calcShrsDemand: (riskyValue)*(1+0.005)];  [self calcShrsDemand: (riskyValue)*(1+0.010)];  [self calcShrsDemand: (riskyValue)*(1+0.020)];#if 0  [self calcShrsDemand: (riskyValue)*(1+0.050)];  [self calcShrsDemand: (riskyValue)*(1+0.10)];  [self calcShrsDemand: (riskyValue)*(1+0.150)];#endif  // Calculate Demand @ perceived value last so probed values  //   are more representative.  [self calcShrsDemand: (riskyValue)*(1-0.00)];  // Go through demand/supply lists and adjust from gross amount of  //   shares demanded at the price point to net shares demanded at  //   the price point.  For bids, this accounts for the fact as the  //   price falls (when clearing), greater bids will already be filled.  dmdTotal = 0;  index = [(id) dmdList begin: scratchZone];  while (( aRequest = [index next])) {    [aRequest setNetUnits: [aRequest getGrossUnits] - dmdTotal];    dmdTotal = [aRequest getGrossUnits];  }  [index drop];  dmdTotal = 0;  index = [(id) supList begin: scratchZone];  while (( aRequest = [index next])) {    [aRequest setNetUnits: [aRequest getGrossUnits] - dmdTotal];    dmdTotal = [aRequest getGrossUnits];  }  [index drop];  // Submit demand schedule to the mkt maker  index = [(id) dmdList begin: scratchZone];  while (( aRequest = [index next])) {    [mktMaker addRiskyDemand: aRequest];  }  [index drop];  index = [(id) supList begin: scratchZone];  while (( aRequest = [index next])) {    // We've been working with neg #'s for supply since this    //   is a number net of what they've currently got.  Need    //   to change to pos # so MktMaker can handle correctly    [aRequest setNetUnits: (-[aRequest getNetUnits])];    [aRequest setGrossUnits: (-[aRequest getGrossUnits])];    [mktMaker addRiskySupply: aRequest];  }  [index drop];  // Clean lists.  Market maker should delete share request objects  //   when he's finished clearing the market  [dmdList removeAll];  [supList removeAll];  return self;}-calcShrsDemand: (double) p0 {  void addAscend(), addDescend();  double expRet;  double grossUnits;  ShareRequest * aRequest;  if (daysTillEarnings == 1) {     expRet= (expP1 - p0 + risky1CF) / p0;  } else {    expRet= (expP1 - p0) / p0;  }  expRiskyRet = expRet;  optRiskyFraction = (expRiskyRet- riskLessRate) /                      (riskAversion * rvar);  // Calculate units to buy/sell at this price  optRiskyUnits = (wealth * optRiskyFraction) /  p0;  //  gross order is amount of demand net of current holdings  grossUnits = optRiskyUnits - riskyUnits;  // if gross > 0, add to demand list (will bid for shares)  // if gross < 0, add to supply list (will offer shares)  // if gross = 0, ignore this price point  aRequest = [ShareRequest create: [self getZone]];  [aRequest setUnitPrice: p0];  [aRequest setGrossUnits: grossUnits];  [aRequest setTrader: (id *) self];  if ([aRequest getGrossUnits]  > 0)     addAscend( (id) dmdList, (id) aRequest);  else if ([aRequest getGrossUnits]  < 0)     addDescend( (id) supList, (id) aRequest);  return self;}-printPortChoice {  if (diagLevel & TRADER_STRATEGY) {#if 0    printf("  Portfolio Choice (BID) r (%f) var (%f)  frac (%f) units (%f)\n",        expRetBid, rvar, optRiskyFractionBid, optRiskyUnitsBid);    printf("  Portfolio Choice (OFFER) r (%f) var (%f)  frac (%f) units (%f)\n",        expRetOffer, rvar, optRiskyFractionSell, optRiskyUnitsSell);#endif  }  return self;}-step {   ShareRequest * aRequest;   double dlyRate, pvif, t1, t2a, t2;   dlyRate = t2 = 0;   if ((diagLevel & METHOD_ENTRY) ||       (diagLevel & METHOD_SCHED))      printf("*** step (EMHFTrader) entry\n");   [super step];   // BANKRUPTCY CODE:  IF WEALTH IS NEGATIVE, THE TRADER MUST    //   CLEAR ALL POSITIONS IN THE RISKY ASSET (LONG OR SHORT)   //   Note:  If the trader already has non-positive wealth, the   //   MktMaker has issued mkt orders on their behalf.  The only   //   things they can do is check liquidity results and exit.  They   //   will not be able to trade until they have sufficient wealth   //   through riskless growth or positive liquidity.   if ([self getWealth] < 0) {     liqNeeds  = [self getLiqNeeds];     wealth = [self getWealth];     [self printWealth];     return self;   } else {     liqNeeds  = [self getLiqNeeds];     wealth = [self getWealth];     [self printWealth];   }   // fundamental strategy is to buy or sell at the   //    fundamental price.  We buy or sell based on   //    portfolio re-balancing needs which arise from   //    liquidity needs and investment gains   //    if (daysTillEarnings == 0) {     [self projectEarnings];     // Use Gordon Model for now     //   NOTE:  all terms are in qtly terms     riskyValue = risky1CF /                (discountRate - riskyGrowthRate);   } else {  // must discount expected earnings and expected             //    price based upon gordon growth model      // some traders change CF projections between earnings     //   annonuncements.     [self updateProjections];     dlyRate = discountRate / 90;     pvif = pow ((double)1+dlyRate, (double)daysTillEarnings);     t1 = risky1CF / pvif;     t2a = (risky1CF * (1+riskyGrowthRate))/                (discountRate - riskyGrowthRate);     t2 = t2a / pvif;     riskyValue = t1 + t2;   }   // derive "expected" clearing price in one period based on today's   //   expected clearing price.  Special case is when dividend is   //   distributed tomorrow.  Then price will drop, but present   //   value of price component of today's price will appreciate   if (daysTillEarnings == 1)      expP1 = t2 * (1+dlyRate);   else     expP1 = riskyValue * (1+dlyRate);   [self printValue];   //  Value must be positive.    //    If value is not positive, try to unload all shares   //     of the risky asset at whatever the market will pay,   //	  if we were short the risky asset, then attempt to   //     close out our position at whatever market will pay   //       if (riskyValue <= 0) {     riskyValue = -1;     optRiskyUnits = 0;     aRequest = [ShareRequest create: [self getZone]];     [aRequest setUnitPrice: -1];     [aRequest setGrossUnits: 0];     [aRequest setNetUnits: riskyUnits];     [aRequest setTrader: (id *) self];     [mktMaker addRiskySupply: aRequest];   } else {     // Fundamental trader will choose a strategy     //   based on what they value the risky asset     //   at.  The number of shares demanded at prices     //   above and below this value is a function of     //   the return variance and the trader's risk     //   aversion.     rvar = [mktStats getRiskyRetVar];     // calculate my demand schedule     [self calcSchedule];   } // end else value is positive/*   [self printPortChoice];   [self printDemand];*/   return self;}-print {  printf("FUND TTEST  \n");  return self;}void addAscend( id list, ShareRequest *s) {  ShareRequest *aRequest;  id index;  if ([list getCount] != 0 ) {    index = [(id) list begin: scratchZone];    while ((aRequest = [index next])) {      // if <= then add in front      if ([s getGrossUnits] <= [aRequest getGrossUnits]) {        [index addBefore: s];        break;      }    }    [index drop];    // if we got to the end of the list, index will be    //   nil, but the trader won't be on teh list    if (aRequest == nil)      [list addLast: s];   } else  // this is the first      [list addLast: s];}void addDescend( id list, ShareRequest *s) {  ShareRequest *aRequest;  id index;  if ([list getCount] != 0 ) {    index = [(id) list begin: scratchZone];    while ((aRequest = [index next])) {      // if >= then add in front      if ([s getGrossUnits] >= [aRequest getGrossUnits]) {        [index addBefore: s];        break;      }    }    [index drop];    // if we got to the end of the list, index will be    //   nil, but the trader won't be on teh list    if (aRequest == nil)      [list addLast: s];   } else  // this is the first      [list addLast: s];}@end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -