我对具有4种资产(债券,股票,股票,现金市场)的投资组合进行MC模拟 我使用每月步骤,我的模拟范围是10年,即120步。我的最终目标是计算年度预期缺口,即获得投资组合回报中最差的5%。
模拟似乎没问题 - 乍一看。然而,我的印象是随着时间的推移漂移在这个过程中占主导地位,所以我的预期缺口甚至是长期的积极因素。当我增加权益权重时,预期的差额最终会减少。当我将每个资产的预期回报设置为零时也是如此,因此增加的风险应该会拖累预期的亏损。 我希望我的代码中有一个错误,但看不到它。任何建议高度赞赏!
#maturity in years
maturity <- 10
#Using monthly steps
nsteps <- maturity*12
dt <- maturity / nsteps
#number of assets
nAssets = 4
#number of simulations
nTrails = 10000
#expected return p.a. for each asset, stored in vector BM.mu
BM.mu <- rep(NA,nAssets)
BM.mu[1] <- 0.0072
BM.mu[2] <- 0.0365
BM.mu[3] <- 0.04702
BM.mu[4] <- 0.0005
#defining variable size
simulated.Returns <- array(NA, dim = c(nsteps+1, nTrails, nAssets))
cumulative.PortReturns <- matrix(rep(NA,nsteps*nTrails), nrow = nsteps, ncol = nTrails)
ES <- rep(NA, maturity)
#defining my monthly correlation and covariance matrix
corr_matrix <- matrix(c(1.000000000, -0.05081574, -0.07697585, 0.0051,
-0.050815743, 1.00000000, 0.80997805, -0.3540,
-0.076975850, 0.80997805, 1.00000000, -0.3130,
0.005095699, -0.35365332, -0.31278506, 1.0000), nrow = 4, ncol = 4)
cov_matrix <- matrix(c(1.44e-04, -2.20e-05, -3.86e-05, 8.44e-08,
-2.20e-05, 1.30e-03, 1.22e-03, -1.76e-05,
-3.86e-05, 1.22e-03, 1.75e-03, -1.81e-05,
8.44e-08, -1.76e-05, -1.81e-05, 1.90e-06), nrow = 4, ncol = 4)
#defining my portfolio weights
port.weights <- c(0.72, 0.07, 0.07, 0.14)
#performing cholesky decomposition
R <- (chol(corr_matrix))
#generating standard-normal, random variables
x <- array(rnorm(nsteps*nTrails*nAssets), c(nsteps*nTrails,nAssets))
#generating correlated standard-normal, random variables
ep <- x %*% R
#defining the drift
drift <- BM.mu - 0.5 * diag(cov_matrix)
#generating asset paths
temp = array(exp(as.vector(drift %*% t(dt)) + t(ep *sqrt(diag(cov_matrix)))), c(nAssets,nsteps,nTrails))
for(i in 2:nsteps) temp[,i,] = temp[,i,] * temp[,(i-1),]
#changing dimension of the array temp from dim(nAssets, nsteps, nTrails) to dim(nsteps, nAssets, nTrails)
simulated.Returns <- aperm(temp,c(2,1,3))
#computing portfolio returns for each simulation (nTrails). To do this, each step is weighted with "port.weights"
#Since I generate continuous returns, I first transform them into discrete, multiply with weights and then transform back into continuous.
for (z in 1:nTrails) {
for (i in 1:nsteps) cumulative.PortReturns[i,z] = log(1+((exp(simulated.Returns[i,,z]-1)-1) %*% port.weights))
}
#Finally I compute the monthly expected shortfall (5%-level) by taking the average of the 5% worst portfolio yields
#I do steps of 12 as I calculate the ES at the end of each year
z = 0
for (i in seq(12, nsteps, by = 12 )) {
z = z + 1
ES[z] <- mean(sort(cumulative.PortReturns[i,]) [1:(0.05*nTrails)])
}
#plotting a sample of simulated portfolio returns
#library(QRM)
plot(as.timeSeries(cumulative.PortReturns[,1:100]), plot.type = 'single')
答案 0 :(得分:1)
根据您的评论,您已将BM.mu
定义为每项资产的年度预期回报。但是,您使用每月而非年度步骤模拟每个样本路径。然后,需要将drift
变量合并到BM.mu
变量中,相应地将#defining the drift
drift <- BM.mu/12 - 0.5 * diag(cov_matrix)
缩放到预期的每月回报:
drift
如果没有这个,您将使用年度预期回报值和月度协方差矩阵计算class unwellBasic: UIViewController, UITextViewDelegate,
UIScrollViewDelegate, UITextFieldDelegate {
@IBOutlet var scrollView: UIScrollView!
weak var activeTextView : UITextView?
weak var activeTextField : UITextField?
@IBOutlet var main: UITextView!
@IBOutlet var initials: UITextField!
@IBOutlet var maleButton: UIButton!
@IBOutlet var femaleButton: UIButton!
@IBOutlet var age: UITextField!
@IBOutlet var test: UITextField!
func registerForKeyboardNotifications() {
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self,
selector: "keyboardWillBeShown:",
name: UIKeyboardWillShowNotification,
object: nil)
notificationCenter.addObserver(self,
selector: "keyboardWillBeHidden:",
name: UIKeyboardWillHideNotification,
object: nil)
}
@IBAction func back(sender: AnyObject) {
self.navigationController?.popViewControllerAnimated(true)
}
@IBAction func next(sender: AnyObject) {
self.performSegueWithIdentifier("bodySegue", sender: self)
}
func tapped() {
initials.resignFirstResponder()
main.resignFirstResponder()
age.resignFirstResponder()
test.resignFirstResponder()
self.activeTextView = nil
}
// Called when the UIKeyboardDidShowNotification is sent.
func keyboardWillBeShown(sender: NSNotification) {
let info: NSDictionary = sender.userInfo!
let value: NSValue = info.valueForKey(UIKeyboardFrameEndUserInfoKey) as! NSValue
let keyboardSize: CGSize = value.CGRectValue().size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
// If active text field is hidden by keyboard, scroll it so it's visible
if self.activeTextView != nil {
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize.height
let activeTextViewRect: CGRect? = self.activeTextView!.frame
let activeTextViewOrigin: CGPoint? = activeTextViewRect?.origin
if (!CGRectContainsPoint(aRect, activeTextViewOrigin!)) {
scrollView.scrollRectToVisible(activeTextViewRect!, animated:true)
}
}
if self.activeTextField != nil {
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize.height
let activeTextViewRect: CGRect? = self.activeTextField!.frame
let activeTextViewOrigin: CGPoint? = activeTextViewRect?.origin
if (!CGRectContainsPoint(aRect, activeTextViewOrigin!)) {
scrollView.scrollRectToVisible(activeTextViewRect!, animated:true)
}
}
}
// Called when the UIKeyboardWillHideNotification is sent
func keyboardWillBeHidden(sender: NSNotification) {
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
scrollView.contentInset = contentInsets
self.scrollView .setContentOffset(CGPointMake(0, 0), animated: true)
self .viewDidLayoutSubviews()
self.activeTextView = nil
}
func textViewDidBeginEditing(textView: UITextView) {
self.activeTextView = textView
scrollView.scrollEnabled = true
}
func textViewDidEndEditing(textView: UITextView) {
self.activeTextView = nil
scrollView.scrollEnabled = false
self.scrollView .setContentOffset(CGPointMake(0, 0), animated: true)
self .viewDidLayoutSubviews()
}
func textFieldDidBeginEditing(textField: UITextField) {
activeTextField = textField
scrollView.scrollEnabled = true
}
func textFieldDidEndEditing(textField: UITextField) {
activeTextField = nil
scrollView.scrollEnabled = false
}
func textFieldShouldReturn(textField: UITextField) -> Bool // called when 'return' key pressed. return NO to ignore.
{
textField.resignFirstResponder()
return true;
}
override func viewDidLoad() {
super.viewDidLoad()
var tap = UITapGestureRecognizer (target: self, action: ("tapped"))
self.view.addGestureRecognizer(tap)
self.main.delegate = self
self.initials.delegate = self
self.age.delegate = self
self.registerForKeyboardNotifications()
}
值。这导致比您预期的更大的漂移,这将影响您所看到的结果。