📄 mktmaker.m
字号:
// MktMaker.m// This file defines the methods for the stock market maker(s).// At this point there will be just one.// The mkt maker is the focal point for the simulation, because// the mkt clearing price is determined here. For now, the// mkt maker will determine a clearing price for both the risky// and riskless assets. The riskless asset will always have a// clearing price of $1/unit since it is in infinite supply.// The clearing price of the risky asset will be determined based// upon the trader's current demands.//// The open question is how to submit these demands to the market// maker. Should they submit 1) a demand function, 2) a share// amount and a limit price, 3) a share amount and no price --// implying that they'll take whatever the market clearing price is.// 4) ???? // or should they have the flexibility to do some combo of the // above.//#import "MktMaker.h"// Implementation of a Market Maker ..@implementation MktMaker-initMktLists { if (diagLevel & METHOD_ENTRY) printf("*** initMktLists (MktMaker) entry\n"); // Create lists to track the traders' demand/supply, then to order // the replies telling them what they've bought/sold mktBidList = [List create: [self getZone]]; mktOfferList = [List create: [self getZone]]; limitBidList = [List create: [self getZone]]; limitOfferList = [List create: [self getZone]]; priceList = [List create: [self getZone]]; // if Seed is zero, use Randomseed to automatically generate if (randomNumSeed == 0) randomGenerator = [MT19937gen create: [self getZone] setStateFromSeed: RANDOMSEED]; else randomGenerator = [MT19937gen create: [self getZone] setStateFromSeed: randomNumSeed]; riskyCFDist = [NormalDist create: [self getZone] setGenerator: randomGenerator setMean: riskyNoiseMean setVariance: riskyNoiseVar]; // GENERATOR for the trader errors // if Seed is zero, use Randomseed to automatically generate // -- if Seed is NON-zero make sure to initialize with the // same seed as the mktmaker. We do this for repeatability. if (randomNumSeed == 0) randomGenerator2 = [MT19937gen create: [self getZone] setStateFromSeed: RANDOMSEED]; else randomGenerator2 = [MT19937gen create: [self getZone] setStateFromSeed: randomNumSeed]; // Initial condition riskyCFNoiseLag = 0; return self;}-(id <MT19937gen>) getRandomGen { return randomGenerator;}-(id <MT19937gen>) getRandomGen2 { return randomGenerator2;}-(long int) getRNGSeed { return ([randomGenerator getInitialSeed]);}-(double) getRiskyCFNoise { return riskyCFNoise;}-(double) getRiskyCFNoiseLag { return riskyCFNoiseLag;}-setDiagLevel: (int) l{ if (diagLevel & METHOD_ENTRY) printf("*** setDiagLevel (MktMaker) entry\n"); diagLevel = l; return self;}-setMktStats: (id) m{ if (diagLevel & METHOD_ENTRY) printf("*** setMktStats (MktMaker) entry\n"); mktStats = m; return self;}-setInventory: (int) x : (int) y { if (diagLevel & METHOD_ENTRY) printf("*** setInventory (MktMaker) entry\n"); riskyInventory = x; riskLessInventory = y; return self;}-setRiskLessRate: (double) r{ if (diagLevel & METHOD_ENTRY) printf("*** setRiskLessRate (MktMaker) entry\n"); riskLessRate = r; return self;}-(double) getRiskLessRate { return riskLessRate;}-setRiskyGrowthRate: (double) r{ if (diagLevel & METHOD_ENTRY) printf("*** setRiskyGrowthRate (MktMaker) entry\n"); riskyGrowthRate = r; return self;}-(double) getRiskyGrowthRate { return riskyGrowthRate;}-setRandomNumSeed: (long int) s{ if (diagLevel & METHOD_ENTRY) printf("*** setRandomNumSeed (MktMaker) entry\n"); randomNumSeed = s; return self;}-setRiskyNoiseMean: (double) m riskyNoiseVar: (double) v{ if (diagLevel & METHOD_ENTRY) printf("*** setRiskyNoiseMean (MktMaker) entry\n"); riskyNoiseMean = m; riskyNoiseVar = v; return self;}-setTraderList: (id) x { if (diagLevel & METHOD_ENTRY) printf("*** setTraderList (MktMaker) entry\n"); traderList = x; return self;}-setShortMargin: (float) s { if (diagLevel & METHOD_ENTRY) printf("*** setShortMargin (MktMaker) entry\n"); shortMarginFactor = s; return self;}-setLongMargin: (float) l { if (diagLevel & METHOD_ENTRY) printf("*** setLongMargin (MktMaker) entry\n"); longMarginFactor = l; return self;}-setPauper: (float) p { if (diagLevel & METHOD_ENTRY) printf("*** setPauper (MktMaker) entry\n"); pauperFactor = p; return self;}-addRiskyDemand: (ShareRequest *) aRequest { Trader * aTrader; void addLimitBid(); double grossUnits, netUnits; double cash, riskyWealth, unitPrice, maxUnits, maxPurchase;// Don't let "bankrupt" traders participate.// Algorithm// if (wealth) <= initWealth * pauperFactor)// - ignore trade// else// - proceed normally// endif if (diagLevel & METHOD_ENTRY) printf("*** addRiskyDemand (MktMaker) entry\n"); aTrader = (Trader *) [aRequest getTrader]; if ([aTrader getWealth] <= ([aTrader getInitWealth]*pauperFactor)) { // ignore this trader's order, since he's too poor to participate if (diagLevel & MKTMAKER_RESTRICTIONS) { printf ("PAUPER (%s) riskyU (%f) riskyP (%f) riskL (%f) wealth (%f)\n", [aTrader getName], aTrader->riskyUnits, [mktStats getRiskyLagPrice:0], aTrader->riskLessUnits, [aTrader getWealth]); } } else { // gross # of units X price offered or last clearing price must // be less than cash available (i.e., riskless units) grossUnits = [aRequest getGrossUnits]; if ([aRequest getUnitPrice] == -1) unitPrice = [mktStats getRiskyPrice]; else unitPrice = [aRequest getUnitPrice]; cash = aTrader->cash + (aTrader->riskLessUnits * [mktStats getRiskLessLagPrice: 0]); riskyWealth = aTrader->riskyUnits * [mktStats getRiskyPrice]; // maxPurchase is the most this trader can spend on risky asset // purchases this period given // their current riskless holdings and current margin requirements // // NOTE: this is found by solving the following equation for the // riskyRequest (#shrs * price offered) this period // // (riskyWealth + riskyRequest) + (cash - riskyRequest) / // (riskyWealth + riskyRequest) = Margin // // thus, maxPurchase is the max riskyRequest allowed // maxPurchase = ((riskyWealth * (1 - longMarginFactor)) + cash) / longMarginFactor; maxUnits = maxPurchase / unitPrice; // if asking for more than is allowed if (grossUnits > maxUnits) { netUnits = [aRequest getNetUnits] - (grossUnits - maxUnits); netUnits = fmax (0, netUnits); [aRequest setNetUnits: netUnits]; } if ([aRequest getNetUnits] > 0) { // track net mkt orders separately if ([aRequest getUnitPrice] == -1) { mktOrderBidAmt = mktOrderBidAmt + [aRequest getNetUnits]; [mktBidList addLast: (ShareRequest *) aRequest]; } else if ([aRequest getUnitPrice] < 0) { // if negative bid, simply ignore it } else { addLimitBid ((id) limitBidList, (ShareRequest *) aRequest); } } } return self;}-addRiskySupply: (ShareRequest *) aRequest { Trader * aTrader; double cash, grossUnits, netUnits; double unitPrice, maxSale, maxPosition, maxUnits, riskyWealth;// double maxDollarAmtShort, maxRiskyUnitsShort, maxUnitsToSell; void addLimitOffer();// Don't allow unlimited short-selling.// Algorithm// if (wealth * marginFactor) <= (riskLessUnits * riskLessPrice)// - ignore trade// else// - proceed normally// endif if (diagLevel & METHOD_ENTRY) printf("*** addRiskySupply (MktMaker) entry\n"); aTrader = (Trader *) [aRequest getTrader]; if (aTrader->riskyUnits < 0) { if (diagLevel & MKTMAKER_RESTRICTIONS) { printf ("SHORTSELL (%s) riskyU (%f) riskyP (%f) riskL (%f) wealth (%f)\n", [aTrader getName], aTrader->riskyUnits, [mktStats getRiskyLagPrice:0], aTrader->riskLessUnits, [aTrader getWealth]); } } // gross # of units is this trader's total order should the mkt clear // at this price grossUnits = [aRequest getGrossUnits]; // if NO SHORT SELLING allowed if (shortMarginFactor == 1) { // can only sell what they have. maxSale = aTrader->riskyUnits; maxUnits = maxSale / [mktStats getRiskyPrice]; } else { // Short trading is limited. The margin rqmt X the risky short postion // must not exceed current NET cash holdings. NET cash holdings are // those in excess of the short risky position. For example, if TOTAL // cash is $150 and the trader is short $100 of the risky asset, then // NET cash holdings are $50. With this in mind, we only have to reduce // the cash amount if the trader is already short. Note that the effect // of this transaction will not (immediately) affect NET cash position. if ([aRequest getUnitPrice] == -1) unitPrice = [mktStats getRiskyPrice]; else unitPrice = [aRequest getUnitPrice]; riskyWealth = aTrader->riskyUnits * [mktStats getRiskyPrice]; cash = aTrader->cash + (aTrader->riskLessUnits * [mktStats getRiskLessLagPrice: 0]); if (riskyWealth < 0) cash = cash + riskyWealth; maxPosition = cash / shortMarginFactor; // if cash is negative, only allow them to unload what they have maxPosition = fmax (0, maxPosition); // can only sell what they have AND move to the maximum short position // for their cash position and current margin rqmnts. maxSale = maxPosition + riskyWealth; maxUnits = maxSale / [mktStats getRiskyPrice]; } if (grossUnits > maxUnits) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -