func (self SGD) addBiasToMatrix(x mat.MatrixRO) *mat.DenseMatrix { xb := mat.Ones(x.Rows(), self.InputDims()+1) for r := 0; r < x.Rows(); r++ { for i := 0; i < self.InputDims(); i++ { xb.Set(r, i, x.Get(r, i)) } } return xb }
// generateReturns generates performance specifically for assets, and returns // separately by asset class as a map // Receiver: SimulationData // Params: numberOfMonths int -- number of periods to model // Returns: returnResultsByAsset func (s *SimulationData) generateReturns(numberOfMonths int) returnResultsByAsset { assetPerformanceData := s.AssetPerformanceData // map[string]Distribution assetClassIds := s.assetClassIds() // []string numberOfAssets := len(assetClassIds) choleskyApplied := s.applyCholeskyDecomposition(numberOfMonths) prices := goMatrix.Zeros(numberOfMonths, numberOfAssets) for row := 0; row < prices.Rows(); row++ { for column := 0; column < prices.Cols(); column++ { var startingValue float64 if row == 0 { startingValue = 0.0 } else { startingValue = prices.Get((row - 1), column) } assetId := assetClassIds[column] // These are sorted alphabetically assetStats := assetPerformanceData[assetId] assetMeanReturn := assetStats.Mean assetStdDev := assetStats.StdDev b := assetMeanReturn - 0.5*math.Pow(assetStdDev, 2) c := assetStdDev * choleskyApplied.Get(row, column) // Can't do the exp(x) in the same step as you need to use the previous value as a starting price! prices.Set(row, column, (startingValue + b + c)) } } for row := 0; row < prices.Rows(); row++ { for column := 0; column < prices.Cols(); column++ { basePrice := prices.Get(row, column) expPrice := math.Exp(basePrice) prices.Set(row, column, expPrice) } } /* Convert prices to relative returns. */ // Add T=0, price=1.0 initialPrices := goMatrix.Ones(1, numberOfAssets) augmentedPrices, _ := initialPrices.Stack(prices) // Create base matrix asRelativeReturns := goMatrix.Zeros(numberOfMonths, numberOfAssets) // Each row in the prices matrix is a list of asset prices in each year - NOT // the progression of a single asset. We'll need to grab columns for that. for column := 0; column < augmentedPrices.Cols(); column++ { priceValues := augmentedPrices.GetColVector(column).Array() // []float64 for periodIndex, periodPrice := range priceValues { if periodIndex == 0 { // Nothing to do on the first column continue } lastPrice := priceValues[periodIndex-1] pctReturn := (periodPrice - lastPrice) / lastPrice asRelativeReturns.Set((periodIndex - 1), column, pctReturn) } } /* */ results := asRelativeReturns.Arrays() // [][]float64 resultsByAsset := returnResultsByAsset{} // map[string][]float64 for _, assetClassId := range assetClassIds { resultsByAsset[assetClassId] = make([]float64, numberOfMonths) } for periodIndex, resultSet := range results { for assetIndex, returnResult := range resultSet { assetClassId := assetClassIds[assetIndex] resultsByAsset[assetClassId][periodIndex] = returnResult } } return resultsByAsset }