📄 mktmaker.m
字号:
else if Mkt bid orders < Mkt Sell order, then price must fall * may have limit sell orders below prior mkt price 1. Determine # shares demanded at each price point below and including last periods clearing price. Price points are determined by examining the limit bid 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. else Mkt bids = Mkt ssell orders 1. Clear mkt at old clearing price filling the entire orders of both sides of the market.*******************************************************************/#endif riskyClearPrice = [mktStats getRiskyLagPrice:0]; // Search limit offer list for price points. Build clearing info list // be sure to include prior clearing price as a price point. aClearInfo = [ClearingInfo create: [self getZone]]; [aClearInfo setPricePoint: riskyClearPrice]; pricePoint = riskyClearPrice; addAscending ((id) priceList, (id) aClearInfo);// [ascendList addAscend: (id) aClearInfo]; index = [(id) limitOfferList begin: scratchZone]; while ((aRequest = [index next])) { // don't want any duplicates if ([aRequest getUnitPrice] != pricePoint) { aClearInfo = [ClearingInfo create: [self getZone]]; [aClearInfo setPricePoint: [aRequest getUnitPrice]]; pricePoint = [aRequest getUnitPrice]; addAscending ((id) priceList, (id) aClearInfo); } } // end search of limitOfferList [index drop]; index = [(id) limitBidList begin: scratchZone]; while ((aRequest = [index next])) { // don't want any duplicates if ([aRequest getUnitPrice] != pricePoint) { aClearInfo = [ClearingInfo create: [self getZone]]; [aClearInfo setPricePoint: [aRequest getUnitPrice]]; pricePoint = [aRequest getUnitPrice]; addAscending ((id) priceList, (id) aClearInfo); } } // end search of limitOfferList [index drop]; shrsBid = shrsOffer = 0; // find turnover at each price point. index = [(id) priceList begin: scratchZone]; while ((aClearInfo = [index next])) { shrsBid = mktOrderBidAmt; shrsOffer = mktOrderOfferAmt; // Determine shrs demanded at each price point. Limit bid list is // in descending order so if I find one that doesn't satisfy, don't // need to search further. indexBid = [(id) limitBidList begin: scratchZone]; while ((aRequest = [indexBid next])) { if ([aRequest getUnitPrice] >= [aClearInfo getPricePoint]) shrsBid = shrsBid + [aRequest getNetUnits]; else break; } [indexBid drop]; // Determine shrs supplied at each price point. At the highest price // point all mkt offers and limit offers are active. At the lowest // price point only mkt orders and possibly limit orders are active. indexOffer = [(id) limitOfferList begin: scratchZone]; while ((aRequest = [indexOffer next])) { if (([aRequest getUnitPrice] <= [aClearInfo getPricePoint])) shrsOffer = shrsOffer + [aRequest getNetUnits]; else break; } [indexOffer drop]; [aClearInfo setDemand: shrsBid]; [aClearInfo setSupply: shrsOffer]; } [index drop]; // Traverse clearingInfoList to determine price point with greatest // turnover. index = [(id) priceList begin: scratchZone]; pricePoint = [mktStats getRiskyLagPrice:0]; // default is last period's price maxTurnover = 0; demand = supply = 0; while ((aClearInfo = [index next])) { turnover = fmin ([aClearInfo getDemand], [aClearInfo getSupply]); // since clearInfo list is in ascending order, this is // strictly greater than. If two pricePoints have samne // turnover, we choose the lowest clearing price. if (turnover > maxTurnover) { maxTurnover = turnover; } } [index drop]; // don't bother if no trades if (maxTurnover > 0) { // If multiple price points have equiv turnover, choose // the one nearest to prior clearing price. minPriceDiff = 1000; index = [(id) priceList begin: scratchZone]; while ((aClearInfo = [index next])) { turnover = fmin ([aClearInfo getDemand], [aClearInfo getSupply]); // Find pricePoint nearest prior clearing price such that // turnover is maximized! if (turnover == maxTurnover) { priceDiff = fabs ([aClearInfo getPricePoint] - [mktStats getRiskyPrice]); if (priceDiff < minPriceDiff) { minPriceDiff = priceDiff; pricePoint = [aClearInfo getPricePoint]; demand = [aClearInfo getDemand]; supply = [aClearInfo getSupply]; } } } [index drop]; } // if no turnover occurs this period, then leave volume at zero and leave // riskyClearPrice at last periods clearing price (the default) if ( ! ((demand == 0) && (supply == 0))) { // clearing price is minimum price point with maximum turnover riskyClearPrice = pricePoint; // Inform traders willing to transact at price point of their // given transaction amounts and the clearing price if (demand > supply) { amtRationedDmd = supply/demand; amtRationedSup = 1; } else { amtRationedDmd = 1; amtRationedSup = demand/supply; } index = [(id) mktBidList begin: scratchZone]; while ((aRequest = [index next])) { [(Trader *) [aRequest getTrader] addRiskyUnits: amtRationedDmd*[aRequest getNetUnits]]; [(Trader *) [aRequest getTrader] subtractCash: [aRequest getNetUnits]*amtRationedDmd*riskyClearPrice]; } [index drop]; index = [(id) mktOfferList begin: scratchZone]; while ((aRequest = [index next])) { [(Trader *) [aRequest getTrader] subtractRiskyUnits: amtRationedSup*[aRequest getNetUnits]]; [(Trader *) [aRequest getTrader] addCash: [aRequest getNetUnits]*amtRationedSup*riskyClearPrice]; } [index drop]; indexBid = [(id) limitBidList begin: scratchZone]; while ((aRequest = [indexBid next])) { if ([aRequest getUnitPrice] >= pricePoint) { [(Trader *) [aRequest getTrader] addRiskyUnits: amtRationedDmd*[aRequest getNetUnits]]; [(Trader *) [aRequest getTrader] subtractCash: [aRequest getNetUnits]*amtRationedDmd*riskyClearPrice]; } else break; } [indexBid drop]; indexOffer = [(id) limitOfferList begin: scratchZone]; while ((aRequest = [indexOffer next])) { if ([aRequest getUnitPrice] <= pricePoint) { [(Trader *) [aRequest getTrader] subtractRiskyUnits: amtRationedSup*[aRequest getNetUnits]]; [(Trader *) [aRequest getTrader] addCash: [aRequest getNetUnits]*amtRationedSup*riskyClearPrice]; } else break; } [indexOffer drop]; } else { // There is NO turnover this period // In this case, we want to report zero turnover, but // we report a market price which is the average of the // highest bid and lowest offer available. // These will be the first on their respective lists. if ([limitBidList getCount] != 0) { aRequest = [limitBidList removeFirst]; highBid = [aRequest getUnitPrice]; // replace so all memory is freed in one place [limitBidList addLast: aRequest]; } else { highBid = 0; } if ([limitOfferList getCount] != 0) { aRequest = [limitOfferList removeFirst]; lowOffer = [aRequest getUnitPrice]; [limitOfferList addLast: aRequest]; } else { lowOffer = 0; } // if have bids & offers, take average. // if missing one or the other, take what I have // if no limit orders avail, report price unchanged if (highBid == 0) riskyClearPrice = lowOffer; else if (lowOffer == 0) riskyClearPrice = highBid; else if ((highBid != 0) && (lowOffer != 0) ) riskyClearPrice = (lowOffer + highBid)/2; else riskyClearPrice = [mktStats getRiskyPrice]; } // end if-else there IS a positive turnover this period // Let everyone with cash invest at riskless rate. // Traders get cash during clearing by selling risky or // riskless assets and through dividends and riskless coupon pmnts // NOTE: We're simply turning all (+ and -) cash positions into // riskless positions since we've been working with their cash // positions while clearing the riskless market. index = [(id) traderList begin: scratchZone]; while ((aTrader = [index next])) { cash = [aTrader checkCash]; // cash amt is number of riskless units since its price is unity, // nevertheless, we'll be overly explicit about the process for // now to maintain some generality aTrader->riskLessBidAmt = cash; [aTrader addRiskLessUnits: aTrader->riskLessBidAmt]; [aTrader subtractCash: (aTrader->riskLessBidAmt)*riskLessClearPrice]; } [index drop]; // DON'T FORGET TO DROP ALL CLEARINGINFO OBJECTS AND PURGE ALL // LISTS!!!! [priceList deleteAll]; // purge lists and delete all shr request objects [mktBidList deleteAll]; [mktOfferList deleteAll]; [limitBidList deleteAll]; [limitOfferList deleteAll]; // Let statistician update history [mktStats addPrices: riskyClearPrice : riskLessClearPrice ]; [mktStats addVol: maxTurnover]; // Reset supply/demand totals mktOrderBidAmt = mktOrderOfferAmt = 0; // Reset CF amounts riskyCF = 0; riskLessCF = 0;// riskLessSupply = riskLessDemand = 0; return self;}// The Bids should be ordered from the highest to the// lowest so that I can sequentially search them// for the most "favorable".void addLimitBid ( id list, ShareRequest * newRequest) { id index; ShareRequest *aRequest; if ([list getCount] != 0) { index = [(id) list begin: scratchZone]; while ((aRequest = [index next])) { // if >= then add in front if ([newRequest getUnitPrice] >= [aRequest getUnitPrice]) { [index addBefore: newRequest]; break; } } [index drop]; // If we got to the end of the list, index will be // nil, but the trader won't be on the list if (aRequest == nil) [list addLast: newRequest]; } else // this is the first [list addLast: newRequest];}// The Offers should be ordered from the lowest to the// highest so that I can sequentially search them// for the most "favorable".void addLimitOffer ( id list, ShareRequest * newRequest) { id index; ShareRequest *aRequest; if ([list getCount] != 0) { index = [(id) list begin: scratchZone]; while ((aRequest = [index next])) { // if <= then add in front if ([newRequest getUnitPrice] <= [aRequest getUnitPrice]) { [index addBefore: newRequest]; break; } } [index drop]; // If we got to the end of the list, index will be // nil, but the trader won't be on the list if (aRequest == nil) [list addLast: newRequest]; } else // this is the first [list addLast: newRequest];}void addAscending ( id list, ClearingInfo *c) { ClearingInfo *aClearInfo; id index; if ([list getCount] != 0 ) { index = [(id) list begin: scratchZone]; while ((aClearInfo = [index next])) { // if <= then add in front if ([c getPricePoint] <= [aClearInfo getPricePoint]) { [index addBefore: c]; 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 (aClearInfo == nil) [list addLast: c]; } else // this is the first [list addLast: c];}@end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -