📄 mktmodelswarm.m
字号:
// Tim Jares -- MktModelSwarm.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 "MktModelSwarm.h"#import <objc/objc-api.h>// Implementation of the model for Mkt.@implementation MktModelSwarm// This method provides access to the counter object in MktModelSwarm.// The object is visible to other classess via message call. This // could evidently be done with probes, but message access seems less// transparent and they point out it's frequently more convenient.+createBegin: (id) aZone { MktModelSwarm * obj; id <ProbeMap> probeMap; // in createBegin, we set up the simulation parameters. // First, call our superclass createBegin -- the return value // is the allocated MktModelSwarm object. obj = [super createBegin: aZone]; // MODIFY: add in defaults for your simulation parameters. // This is where I will add such things as: // NOTE: ** probably will move this logic to mktMaker ... // this may eventually contain # or mkt makers or mkts, etc... // - number of agents // - endowed wealth // - agent types/strategies // - etc. // total is just sum of types. This is in here because it // may eventually be useful to let traders mutate or evolve // with regard to type. This total will just let me know how // many there are.... // the next 4 items aren't used right now, but may come in handy // if inventory is added at some point obj->riskyEndow = 1; obj->riskLessEndow = 1; // specialist's inventory .. obj->riskyInventory = 0; obj->riskLessInventory = -1; // unlimited // ENTER ANNUAL DATA, CONVERT TO APPROPRIATE GRANULARITY // 3% annual percentage rate obj->riskLessRate = 0.03; // 3% annual percentage rate obj->riskyGrowthRate = 0.03; obj->riskyNoiseMean = 0; obj->riskyNoiseVar = 0.04; obj->liqMean = 0; obj->liqVar = 0.00000001; obj->shortMarginFactor = 1; // no short selling obj->longMarginFactor = 1; // no purchasing risky on margin obj->pauperFactor = 0; // when wealth is GONE! obj->randomNumSeed = 0; // default AUTO generation // seems to be the most helpful level obj->diagLevel = 0; // Now build a customized probe map. Without a probe map, // the default is to show all variables and messages. Here // we choose to customize the appearance of the probe. That // is, give it a nicer interface. probeMap = [EmptyProbeMap createBegin: aZone]; [probeMap setProbedClass: [self class]]; probeMap = [probeMap createEnd]; // MODIFY: add your own probes for your parameters./* [probeMap addProbe: [probeLibrary getProbeForVariable: "riskySupply" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskLessSupply" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "numFundTraders" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "numNoiseTraders" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "numTraders" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskyEndow" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskLessEndow" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskyClearPrice" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskLessClearPrice" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "risky1LagPrice" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskLess1LagPrice" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskyCF" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskyGrowthRate" inClass: [self class]]]; [probeMap addProbe: [probeLibrary getProbeForVariable: "riskLessCF" inClass: [self class]]]; [probeLibrary setProbeMap: probeMap For: [self class]];*/ return obj;}// MODIFY: possible creation objects here.-createEnd { return [super createEnd];}-buildObjects { // Create pointer to a trader so that the traders can be allocated // and assigned to their particular list. Trader * aTrader;// int y; char * tClassStr, * objNamStr;// int tCnt; int rEndow, rlEndow; id aFileObj,aNameObj; id tClass; char * modSetup; char * traderSetup; char * rnSeed; char * getenv(); Class objc_lookup_class (); /* char *traderType[] = {"Fundamental", "Noise"}; char *traderColors[] = {"blue", "green", "blue", "green"};*/ [super buildObjects]; // We will load parameters from a file so we don't have // to recompile everytime we want to change something. // modSetup = getenv("MODSETUP"); if (modSetup == NULL) [ObjectLoader load: self fromFileNamed: "model.setup"]; else [ObjectLoader load: self fromFileNamed: modSetup]; // if an environment variable RNSEED is defined, override setup file rnSeed = getenv("RNSEED"); if (modSetup != NULL) randomNumSeed = atol (rnSeed); // MODIFY: create your simulation objects and set them up from the // model parameters. // SKIP THIS FOR NOW *********** // I'm trying to follow the logic of the final tutorial. I want // the mktmaker to be a subswarm of the mktswarm. (I think) So, // I'm just duplicating the relationship between the observer // and the primary swarm model. // SKIP THIS FOR NOW *********** // Create and initialize mkt (passive) statistician mktStats = [MktStats create: [self getZone]]; [mktStats setDiagLevel: diagLevel]; [mktStats initHistory]; // The above note may be for later, for now the MktMaker will // be in the mktmodelswarm with the traders. mktMaker = [MktMaker createBegin: [self getZone]]; // ** may also want to tell the mkt maker how to determine the mkt // clearing price here, akin the traders' strategies mktMaker = [mktMaker createEnd]; [mktMaker setDiagLevel: diagLevel]; [mktMaker setMktStats: mktStats]; [mktMaker setInventory: riskyInventory : riskLessInventory]; // CONVERT riskless to daily and growth to qtly rates [mktMaker setRiskLessRate: riskLessRate/360]; [mktMaker setRiskyGrowthRate: riskyGrowthRate/4]; [mktMaker setRandomNumSeed: randomNumSeed]; [mktMaker setRiskyNoiseMean: riskyNoiseMean riskyNoiseVar: riskyNoiseVar]; [mktMaker setShortMargin: shortMarginFactor]; [mktMaker setLongMargin: longMarginFactor]; [mktMaker setPauper: pauperFactor]; // must be after set noise dist, since it's used here [mktMaker initMktLists]; // Create and initialize mkt (passive) fundamental price reporter reporter = [Reporter createBegin: [self getZone]]; [reporter setDiagLevel: diagLevel]; [reporter setMktStats: mktStats]; [reporter setMktMaker: mktMaker]; [reporter createEnd]; // I will create the traders in list(s) or queue(s) // in order to keep track of them for probing, aggregating, // etc. See SFI working paper 97-01-002 in order to get some // tips on tracking "groups" of Mortal agents. This is // appropriate since bankrupt agents in this simulation "die". // Create lists to track the traders as a whole and by type traderList = [List create: [self getZone]]; // This is where the agents are actually created. They will // be informed of their "defaults" via the message // mechanism. // Traders and their lists will be built based upon the classes // and numbers in the trader.setup file. // NOTE: There is really no format checking right now, so be // careful to be sure the file has valid classes and is of // the correct format: // CLASSNAME NUMBER_OF_TRADERS // LOAD TRADER CLASSES numTraders = 0; tClassStr = [[self getZone] alloc: 64]; objNamStr = [[self getZone] alloc: 64]; traderSetup = getenv("TRADERSETUP"); if (traderSetup == NULL) aFileObj = [InFile create: [self getZone] setName: "trader.setup"]; else aFileObj = [InFile create: [self getZone] setName: traderSetup]; while ([aFileObj getWord: tClassStr] != 0) { [aFileObj getInt: (int *) &rEndow]; [aFileObj getInt: (int *) &rlEndow]; if (diagLevel & MKTMODELSWARM) { printf ("\n <%s> <%d> <%d> \n", tClassStr, rEndow, rlEndow); } tClass = objc_lookup_class (tClassStr); numTraders++; sprintf (objNamStr, "%s%d", tClassStr, numTraders); aNameObj = [UName create:[self getZone] setBaseName: objNamStr]; // Create the trader for this class aTrader = [(id) tClass createBegin: [self getZone]]; [aTrader setMktMaker: mktMaker]; [aTrader setMktStats: mktStats]; [aTrader setLiqMean: liqMean liqVar: liqVar]; [aTrader setDiagLevel: diagLevel]; [aTrader setTraderName: (char *) [aNameObj getNewName]]; [aTrader setEndow: rEndow : rlEndow]; aTrader = [aTrader createEnd]; // Add to all proper lists [traderList addLast: aTrader]; } [aFileObj drop]; [[self getZone] free: tClassStr]; [[self getZone] free: objNamStr]; // Tell the market maker about the participants // NOTE: this may not really be necessary .... // may eventually want traders to be dynamic, the mkt maker // may be able to track participants by simply observing // their "demand requests" [mktMaker setTraderList: traderList]; // Only mess with HISTO w/ graphics if (swarmGUIMode == 1) { useHisto = [Histogram createBegin: globalZone]; SET_WINDOW_GEOMETRY_RECORD_NAME (useHisto); [useHisto setBinCount: numTraders]; useHisto = [useHisto createEnd]; [useHisto setWidth: 400 Height: 250];/* [useHisto setNumPoints: 2 Labels: traderType Colors: traderColors];*/ [useHisto setLabels: NULL count: numTraders]; [useHisto setColors: NULL count: numTraders];/* Labels: NULL Colors: NULL];*/ [useHisto setTitle: "Wealth of Traders"]; [useHisto setAxisLabelsX: "Trader" Y: "Wealth"]; [useHisto pack];// #if 0/* Comment or if-def these out while running the batch stuff. Their not needed for batch execution and may add some overhead. NOTE: must do the same for the schedule stuff.*/ // create graph for price of risky asset wealthGraph = [Graph create: globalZone]; [wealthGraph setTitle: "Class Wealth vs. Time"]; [wealthGraph setAxisLabelsX: "time" Y: "wealth"]; [wealthGraph setWidth: 400 Height: 250]; [wealthGraph pack]; [wealthGraph setScaleModeX: 1 Y: 0]; // create elements to draw on the graph traderElement = [wealthGraph createElement]; [[[traderElement setLabel: "all traders"] setColor: "black"] setWidth: 3]; traderGrapher = [ActiveGraph createBegin: [self getZone]]; [traderGrapher setElement: traderElement]; [traderGrapher setDataFeed: self]; [traderGrapher setProbedSelector: M(getTotalWealthPercent)]; traderGrapher = [traderGrapher createEnd]; // create elements to draw on the graph BHElement = [wealthGraph createElement]; [[[BHElement setLabel: "BuyHold"] setColor: "blue"] setWidth: 3]; BHGrapher = [ActiveGraph createBegin: [self getZone]]; [BHGrapher setElement: BHElement]; [BHGrapher setDataFeed: self]; [BHGrapher setProbedSelector: M(getBHWealth)]; BHGrapher = [BHGrapher createEnd]; // create elements to draw on the graph EMHFElement = [wealthGraph createElement]; [[[EMHFElement setLabel: "EMHFTrader"] setColor: "green"] setWidth: 3]; EMHFGrapher = [ActiveGraph createBegin: [self getZone]]; [EMHFGrapher setElement: EMHFElement]; [EMHFGrapher setDataFeed: self]; [EMHFGrapher setProbedSelector: M(getEMHFWealth)]; EMHFGrapher = [EMHFGrapher createEnd]; // create elements to draw on the graph UEMHFElement = [wealthGraph createElement]; [[[UEMHFElement setLabel: "UEMHFTrader"] setColor: "yellow"] setWidth: 3];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -