📄 mktmaker.m
字号:
// reduce netUnits by the number that grossUnits exceeds what this // trader has available. netUnits = [aRequest getNetUnits] - (grossUnits - maxUnits); netUnits = fmax (0, netUnits); [aRequest setNetUnits: netUnits]; }// ***************************************************************************// ADD ORDER TO PROCESSING LISTS if ([aRequest getUnitPrice] == -1) { mktOrderOfferAmt = mktOrderOfferAmt + [aRequest getNetUnits]; [mktOfferList addLast: (ShareRequest *) aRequest]; } else if ([aRequest getUnitPrice] < 0) { // if negative offer, simply ignore it } else { addLimitOffer ((id) limitOfferList, (ShareRequest *) aRequest); } // *************************************************************************** return self;}/*-addRiskLessDemand: (Trader *) aTrader { if (aTrader->riskLessBidAmt > 0) { [riskLessDemandList addLast: aTrader]; riskLessDemand = riskLessDemand + aTrader->riskLessBidAmt; } return self;}*//*-addRiskLessSupply: (Trader *) aTrader { if (aTrader->riskLessOfferAmt > 0) { [riskLessSupplyList addLast: aTrader]; riskLessSupply = riskLessSupply + aTrader->riskLessOfferAmt; } return self;}*/-print { printf("MKTMAKER TESTS \n"); return self;} // NOTE: payInterest must be scheduled after pay earnings so that // the riskyCF is correct for those days that earnings are paid. This // is done so that all other days have a riskyCF of zero.-payInterest { Trader * aTrader; id index; if ((diagLevel & METHOD_ENTRY) || (diagLevel & METHOD_SCHED)) printf("*** payInterest (MktMaker) entry, (%d)\n", (int) getCurrentTime()); // Cleanup from last period -- if necessary // Prepare info for traders to determine their demand -- if neccesary // Determine riskLess mkt clearing price -- set at $1 for now riskLessCF = 1 * riskLessRate; riskLessClearPrice = 1; // // Distribute interest to ALL shareholders // NOTE: this applies to everyone, whether they're // trading or not. // index = [(id) traderList begin: scratchZone]; while ((aTrader = [index next])) { // coupon pmt [aTrader addCash: aTrader->riskLessUnits*riskLessRate]; if (diagLevel & MKTMAKER_TRDR_WEALTH) { printf ("Wealth of <%s> is %f\n", [aTrader getName], [aTrader getWealth]); } } [index drop]; // Tell statistician [mktStats addRiskLessCF: riskLessCF : riskyCF]; return self;}-payEarnings { Trader * aTrader; id index; if ((diagLevel & METHOD_ENTRY) || (diagLevel & METHOD_SCHED)) printf("*** payEarnings (MktMaker) entry, (%d)\n", (int) getCurrentTime()); // Cleanup from last period -- if necessary // Prepare info for traders to determine their demand -- if neccesary // DETERMINE DIVIDEND PER SHARE riskyCFNoise = [riskyCFDist getDoubleSample]; // for now, steady growth rate to determine CF (div)... // It is possible to have a negative CF, but we don't // want it to persist. If last period was negative, just // use noise to set this period's CF. This prevents an // explosive downturn in CFs. // Use ARMA(1,1) process as described in Kmenta p. 529 // with lambda = 0.75 riskyCF = (1+riskyGrowthRate) * ([mktStats getEarningsLag:0]) + riskyCFNoise - (0.75) * riskyCFNoiseLag; // Save for next period riskyCFNoiseLag = riskyCFNoise; if (diagLevel & MKTMAKER_TSERIES) { printf ("Earnings[0] <%f> and Earnings[-1] <%f> Noise <%f>\n", riskyCF, [mktStats getEarningsLag:0], riskyCFNoise); } // // Distribute dividends to ALL shareholders // NOTE: this applies to everyone, whether they're // trading or not. Some may be restricted // from trading for a period of time due // to margin, short-selling, or wealth // limitations. // index = [(id) traderList begin: scratchZone]; while ((aTrader = [index next])) { // earnings [aTrader addCash: aTrader->riskyUnits*riskyCF]; if (diagLevel & MKTMAKER_TRDR_WEALTH) { printf ("Wealth of <%s> is %f\n", [aTrader getName], [aTrader getWealth]); } } [index drop]; // Tell statistician [mktStats addEarnings: riskyCF]; return self;}-printDemandSched { id index; ShareRequest * aReq; if (diagLevel & MKTMAKER_CLEARING) { printf ("\n------------------DEMAND SCHEDULE------------------\n"); printf (" MktBidList\n"); index = [(id) mktBidList begin: scratchZone]; while ((aReq = [index next])) { printf (" [%s] Bid (%f) Amt (%f) \n", [(Trader *) [aReq getTrader] getName], [aReq getUnitPrice], [aReq getNetUnits]); } [index drop]; printf (" MktOfferList\n"); index = [(id) mktOfferList begin: scratchZone]; while ((aReq = [index next])) { printf (" [%s] Offer (%f) Amt (%f) \n", [(Trader *) [aReq getTrader] getName], [aReq getUnitPrice], [aReq getNetUnits]); } [index drop]; printf (" LimitBidList\n"); index = [(id) limitBidList begin: scratchZone]; while ((aReq = [index next])) { printf (" [%s] Bid (%f) Amt (%f) \n", [(Trader *) [aReq getTrader] getName], [aReq getUnitPrice], [aReq getNetUnits]); } [index drop]; printf (" LimitOfferList\n"); index = [(id) limitOfferList begin: scratchZone]; while ((aReq = [index next])) { printf (" [%s] Offer (%f) Amt (%f) \n", [(Trader *) [aReq getTrader] getName], [aReq getUnitPrice], [aReq getNetUnits]); } [index drop]; printf ("\n------------------END DEMAND SCHEDULE------------------\n"); } // end if CLEARING LOGGING IS ON return self;}-checkBankruptcies { void addLimitBid(), addLimitOffer(); ShareRequest * aRequest; Trader * aTrader; id index; index = [(id) traderList begin: scratchZone]; while ((aTrader = [index next])) { // BANKRUPTCY CODE: IF WEALTH IS NEGATIVE, THE TRADER MUST // CLEAR ALL POSITIONS IN THE RISKY ASSET (LONG OR SHORT) aRequest = [ShareRequest create: [self getZone]]; [aRequest setUnitPrice: -1]; [aRequest setTrader: (id *) aTrader]; // force bankrupt traders to liquidate all RISKY positions if ([aTrader getWealth] <= 0) { if (aTrader->riskyUnits > 0) { // have some and MUST sell ALL [aRequest setGrossUnits: aTrader->riskyUnits]; [aRequest setNetUnits: aTrader->riskyUnits]; mktOrderOfferAmt = mktOrderOfferAmt + [aRequest getNetUnits]; [mktOfferList addLast: aRequest]; } else if (aTrader->riskyUnits < 0) { // MUST close out SHORT positions [aRequest setGrossUnits: -(aTrader->riskyUnits)]; [aRequest setNetUnits: -(aTrader->riskyUnits)]; mktOrderBidAmt = mktOrderBidAmt + [aRequest getNetUnits]; [mktBidList addLast: aRequest]; } // Be sure to note when this trader's wealth became non-positive [aTrader setBRPeriod: [mktStats getPeriod]]; } } [index drop]; return self;}-countShares { Trader * aTrader; id index; double totalShrs; totalShrs = 0; index = [(id) traderList begin: scratchZone]; while ((aTrader = [index next])) { totalShrs = totalShrs + aTrader->riskyUnits; } [index drop]; if (diagLevel & MKTMAKER_CLEARING) printf ("TOTAL RISKY SHARES(%d) = %f", [mktStats getPeriod], totalShrs); return self;}//// LET WEALTH GO NEGATIVE FOR NOW....//// Mkt maker must clear both the riskless and risky mkts simultaneously// in case people want to fund risky purchases with riskless sales. Or// in the future if risky sales fund other risky purchases....// 1) Handle riskless sales, since they are certain to clear and// money can go into their cash account.// 2) -step { ClearingInfo *aClearInfo; Trader * aTrader; ShareRequest * aRequest; // id index, bidIndex, offerIndex; id index, indexBid, indexOffer; double amtRationedDmd, amtRationedSup; double cash; double shrsBid, shrsOffer; double pricePoint; double priceDiff, minPriceDiff; double turnover, maxTurnover; double demand, supply; double highBid, lowOffer; void addAscending(); int period; period = [mktStats getPeriod]; if ((diagLevel & METHOD_ENTRY) || (diagLevel & METHOD_SCHED)) printf("*** step (MktMaker) entry\n"); // PRINT EVERYTIME FOR NOW [self printDemandSched]; // INITIALIZE risky volume for this period// riskyVol = 0; // Determine riskLess mkt clearing price -- set at $1 for now riskLessClearPrice = 1; // Convert ALL riskless holdings to cash in case it's // need to buy risky asset. ALL will be reinvested at // riskless rate when risky mkt clears // NOTE: Since riskless units can be negative (borrowing), // this sequence can work to decrease cash (possibly negative). // This causes no problems unless total wealth is non- // postitive. Any cash positions (+ or -) will be closed // out after the risky market is cleared. index = [(id) traderList begin: scratchZone]; while ((aTrader = [index next])) { [aTrader addCash: (aTrader->riskLessUnits)*riskLessClearPrice]; [aTrader subtractRiskLessUnits: aTrader->riskLessUnits]; if (diagLevel & MKTMAKER_TRDR_WEALTH) { printf ("<%s> has (%f) risky (%f) riskless (%f) cash (%f)\n", [aTrader getName], [aTrader getWealth], aTrader->riskyUnits, aTrader->riskLessUnits, aTrader->cash); } } [index drop];#if 0/****************************************************************** Mkt Clearing Algorithm If Mkt bid order > Mkt Sell orders, then price must rise to clear * may have limit bid orders above prior mkt price 1. Determine # shares demanded at each price point above and including last periods clearing price. Price points are determined by examining the limit offer list and last period's clearing price. 2. Determine # of shares supply at each price point. 3. Choose clearing price as LOWEST price at which the greatest amount of turnover will occur. We will "ration" whichever side has the most available shares. The side with the fewest available shares will receive their full order.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -