?? agent.java
字號:
package asm;import java.util.Vector;/** * Title: Artificial Stock Market * Description: 人工模擬股市(來源:SFI的Swarm版本)的Java版本 * Copyright: Copyright (c) 2003 * Company: http://agents.yeah.net * @author jake * @version 1.0 */public class Agent { static double minstrength;//最小的規則適應度 public double demand; /*對股票的需求量" bid or -offer"*/ public double profit; /*當期贏得的利潤" exp-weighted moving average "*/ public double wealth; /*總財富" total agent wealth "*/ public double position;/*股票的持有量" total shares of stock "*/ public double cash;/*當期的現金量" total agent cash position "*/ public double initialcash;//初始時刻的現金 public double minholding;//最小的持股量 public double mincash;//最小現金量 public double intrate;//利率 public double intratep1;//利率+1 public double price;//當前的股票價格 price is maintained by World public double dividend;//當前的股息 dividend is maintained by World public int myID; int currentTime; /*當前時間"The agent regularly checks with Swarm to see what time it is"*/ int lastgatime; /*上一次運行遺傳算法的時間" last time period when the GeneticAlgorithm was run"*/ double avspecificity; /*平均特異性'average specificity of active forecasts"*/ double forecast; /*對price+dividend的預測值"prediction of stock price: (trialprice+dividend)*pdcoeff + offset."*/ double lforecast; /*上一次的預測值"lagged forecast: forecast value from previous period"*/ double global_mean; /*"price+dividend"*/ double realDeviation; /*預測與現實的差" ftarget-lforecast: how far off was the agent's forecast?"*/ double variance; /*一個加權平均數公式:bv*variance + av*deviation*deviation"an Exp.Weighted MA of the agent's historical variance: Combine the old variance with deviation^squared, as in: bv*variance + av*deviation*deviation"*/ double pdcoeff; /*預測系數" coefficient used in predicting stock price, recalculated each period in prepareForTrading"*/ double offset; /*預測系數" coefficient used in predicting stock price, recalculated each period in prepareForTrading"*/ double divisor; /*計算股票需求量的一個系數" a coefficient used to calculate demand for stock. It is a proportion (lambda) of forecastvar (basically, accuracy of forecasts)"*/ int gacount; /*運行過遺傳算法的次數" how many times has the Genetic Algorithm been used?"*/ AgentParam privateParams; /*關于agent參數的一個集合"BFParams object holds parameters of this object"*/ Vector fcastList; /*預測規則的列表"A Swarm Array, holding the forecasts that the agent might use"*/ Vector activeList; /*激活的預測規則列表"A Swarm list containing a subset of all forecasts"*/ Vector oldActiveList; /*激活的預測規則列表的拷貝"A copy of the activeList from the previous time step"*/ Vector History; //關于agent的歷史紀錄 World worldForAgent; //當前的世界狀態和編碼 AsmModel local; //對于AsmModel的一個拷貝/*"This tells BFagents where they should look to get the default parameters. it should give the agent an object from the BFParams class."*/void setBFParameterObject(AgentParam x){ privateParams=x;}/*" Sets a world for an agent. It is a class method as it is used inboth class and instance methods in BFagent."*/void setWorld(World aWorld){ worldForAgent = aWorld;}/*" Sets the IVAR intrate and uses that to calculate intratep1 (intrate + 1)."*/void setintrate(double rate){ //設定利率 intrate = rate; intratep1 = intrate + 1.0;}/*" Sets the borrowing and short selling constraints, i.e., the // values can be negative. It sets values of the IVARS minholding and mincash"*/void setminHolding(double holding,double minimumcash){ minholding = holding; mincash = minimumcash;}/*" Sets the initial stock holdings of each agent. It is the * designated initializer. Most agent classes will have additional * initialization, but should do [super setInitialHoldings] to run * this first. It will initialize instance variables common to all * agents, setting profit,wealth, and position equal to 0, and it sets * the variable cash equal to initialcash "*/void setInitialHoldings(){ //幾個參數的初始化 profit = 0.0; wealth = 0.0; cash = initialcash; position = 0.0;}/*" Sets an instance variable of agent, price, to the current price which is controlled by the object known as "world". Please note this assumes world is already set. "*/void getPriceFromWorld(){ price = worldForAgent.getPrice();}/*"Sets an instance variable of agent, dividend, to the current dividend. That information is retrieved from the object known as "world"."*/void getDividendFromWorld(){ dividend = worldForAgent.getDividend();}void creditEarningsAndPayTaxes()/*"Sent to each agent after a dividend is declared. The agents * receive the dividend for each unit of stock they hold. Their cash" * in the fixed asset account also receives its interest. Then taxes * are charged on the previous total wealth, at a rate that balances * the interest on cash -- so if the agent had everything in cash it * would end up at the same place. * This is done in each period after the new dividend is declared. It is * not normally overridden by subclases. The taxes are assessed on the * previous wealth at a rate so that there's no net effect on an agent * with position = 0. * * In principle we do: * wealth = cash + price*position; // previous wealth * cash += intrate * cash + position*dividend; // earnings * cash -= wealth*intrate; // taxes * but we cut directly to the cash: * cash -= (price*intrate - dividend)*position" */{//對每個agent進行征稅和分紅 getPriceFromWorld(); getDividendFromWorld();// Update cash cash -= (price*intrate - dividend)*position; if (cash < mincash)cash = mincash;// Update wealth wealth = cash + price*position;}double constrainDemand(double slope[],double trialprice)/*" Method used by agents to constrain their demand according to the * mincash and minholding constraints. * It checks "demand" against the * mincash and minholding constraints and clips it if necessary, then * also setting *slope. For use within subclass implementations of * getDemandAndSlope: forPrice:. Used only by agents that work with * the Slope Specialist."*/{//檢查交宜人的需求量是否過量。如果是買入,則察看他的現金是否還夠,否則察看他能否賣出那么多股票。// If buying, we check to see if we're within borrowing limits,// remembering to handle the problem of negative dividends -// cash might already be less than the min. In that case we// freeze the trader. if (demand > 0.0) { if (demand*trialprice > (cash - mincash)) { if (cash - mincash > 0.0) { demand = (cash - mincash)/trialprice; slope[0] = -demand/trialprice; } else { demand = 0.0; slope[0] = 0.0; } } }// If selling, we check to make sure we have enough stock to sell else if (demand < 0.0 && demand + position < minholding) { demand = minholding - position; slope[0] = 0.0; } return demand;}/*"initForecasts. Creates BFCast objects (forecasts) and puts them into an array called fCastList. These are the "meat" of this agent's functionality, as they are repeatedly updated, improved, and tested in the remainder of the class. Please note each BFagent has a copy of the default params object called privateParams. It can be used to set individualized values of settings in BFParams for each agent. That would allow true diversity! I don't see how that diversity would be allowed for in the ASM-2.0."*/void initForecasts(){ //初始化自己所有的預測規則 int sumspecificity = 0; int i; Forecast aForecast=new Forecast(privateParams.condbits); int numfcasts;// Initialize our instance variables //all instances of BFagent can use the same BFParams object. //ASM-2.0 was written that way, something like: // privateParams= params; // That seemed fraught with danger, with all instances having // read/write access to a global parameter object, so now I'm // creating a copy that each agent can have and individualize. //privateParams = [params copy: [self getZone]]; //If you want to customize privateParams, this is the spot! numfcasts = privateParams.numfcasts; //fcastList=[Array create: [self getZone] setCount: numfcasts]; avspecificity = 0.0; gacount = 0; variance = privateParams.initvar; getPriceFromWorld(); getDividendFromWorld(); global_mean = price + dividend; forecast = lforecast = global_mean; // Initialize the forecasts, put them into Swarm Array //keep the 0'th forecast in a "know nothing" condition //[fcastList atOffset: 0 put: [self createNewForecast]]; //fcastList.addElement(new Forecast(worldForAgent.NWORLDBITS)); //create rest of forecasts with random conditions //初始化每條規則,主要讓規則的if部分隨機取0,1,2,then部分在允許范圍內取值。 for(i = 0; i < numfcasts; i++){ aForecast=createNewForecast(); setConditionsRandomly(aForecast); fcastList.addElement(aForecast); //put aForecast into Swarm array "fcastlist" }/* Compute average specificity */ //pj: Here is the proper way to iterate over Swarm collections //計算平均特異度 int size=fcastList.size(); for(i=0;i<size;i++){ aForecast=(Forecast)(fcastList.elementAt(i)); sumspecificity += aForecast.specificity; } avspecificity = (double) sumspecificity/(double)numfcasts;}/*"Creates a new forecast object (instance of BFCast), with all condition bits set to 00 here, meaning "don't care. It also sets values for the other coefficients inside the BFCast. This method is accessed at several points throughout the BFagent class when new forecasts are needed."*/Forecast createNewForecast(){ //新建一條規則 Forecast aForecast=new Forecast(privateParams.condbits); //needed to set values of a,b,and c //設置a,b,c系數的取值范圍 double abase = privateParams.a_min + 0.5*(1.0-privateParams.subrange)*privateParams.a_range; double bbase = privateParams.b_min + 0.5*(1.0-privateParams.subrange)*privateParams.b_range; double cbase = privateParams.c_min + 0.5*(1.0-privateParams.subrange)*privateParams.c_range; double asubrange = privateParams.subrange*privateParams.a_range; double bsubrange = privateParams.subrange*privateParams.b_range; double csubrange = privateParams.subrange*privateParams.c_range; aForecast.a=abase + Math.random()*asubrange; aForecast.b=bbase + Math.random()*bsubrange; aForecast.c=cbase + Math.random()*csubrange; aForecast.condbits=privateParams.condbits; aForecast.nnulls=privateParams.nnulls; aForecast.bitcost=privateParams.bitcost; aForecast.forecast=0.0; aForecast.lforecast=global_mean; aForecast.variance=privateParams.newfcastvar; //same as bfagent's init aForecast.strength=0.0; return aForecast;}/*"Take a forecast object and randomly change the bits that govern which conditions it monitors. This appears to be a piece of functionality that could move to the BFCast class itself. There were quite a few of these details floating around in BFagent at one time, many are gone now."*///隨機設置預測規則的if部分void setConditionsRandomly(Forecast fcastObject){ int bit; double problist[];//概率列表,判斷每個位是否設置為不在乎2 problist=new double[privateParams.condbits]; String conditions=""; getProbList(problist);// = double[privateParams.getProbListPtr]; for(bit=0; bit< privateParams.condbits; bit++){ if (Math.random() < problist[bit]){ conditions+=String.valueOf((int)(Math.random()*2)); fcastObject.incrSpecificity(); fcastObject.updateSpecfactor(); } else{ conditions+="2"; } } fcastObject.conditions=conditions;}void prepareForTrading() /*" * Set up a new active list for this agent's forecasts, and compute the * coefficients pdcoeff and offset in the equation * forecast = pdcoeff*(trialprice+dividend) + offset * * The active list of all the fcasts matching the present conditions is saved * for later updates. "*/{ //準備交易,根據當前的世界的編碼信息,激活規則 double weight, countsum, forecastvar=0.0; int mincount; int nactive; String myworld; Forecast aForecast=new Forecast(privateParams.condbits); Forecast bestForecast; double maxstrength; currentTime = getCurrentTime(); //如果滿足條件,則激活遺傳算法優化每一個規則 if (currentTime >= privateParams.firstgatime && Math.random() < privateParams.gaprob) { local.localasm.setStatus("正在執行遺傳算法"); performGA(); activeList.removeAllElements(); } //this saves a copy of the agent's last as lforecast. lforecast = forecast; //得到世界當前的編碼 myworld = collectWorldData(); //根據編碼激活規則 updateActiveList(myworld); maxstrength = -1e50; bestForecast = null; nactive = 0; mincount = privateParams.mincount; //在激活的規則列表中找出適應度最高的規則 int size=activeList.size(); for(int i=0;i<size;i++){ aForecast=(Forecast)activeList.elementAt(i); if(i==0&&bestForecast==null)bestForecast=aForecast; aForecast.lastactive=currentTime; if(aForecast.incrCount()>= mincount){ double strength=aForecast.strength; ++nactive; if (strength > maxstrength||(strength<-1e50&&maxstrength==-1e50)){ maxstrength = strength; bestForecast= aForecast; } } } //如果有規則被激活,則選擇最好的規則作為參數 if (nactive>=1) // meaning that at least some forecasts are active { pdcoeff = bestForecast.a; offset = bestForecast.b*dividend + bestForecast.c; if(privateParams.individual==1){ forecastvar = bestForecast.variance; }else{ forecastvar = variance; } } else //如果沒有規則被激活 meaning "nactive" zero, no forecasts are active { countsum = 0.0; pdcoeff = 0.0; double pdcoeff1=0; double offset1=0; offset = 0.0; mincount = privateParams.mincount; //針對每條規則計算加權平均的預測系數
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -