I spent some time today learning the nnet
package in R. nnet
makes building, training, and predicting with neural nets really easy. Here is a quick tour.
Keep in mind, my objective here is to get a sense of the package, rather than demonstrate how it could be used. In addition, I have drawn heavily from the example used in the book Mastering R for Quantitative Finance, which is where I learned the package in the first place.
GET & ORGANIZE DATA
As usual, we have to get and organize some data to test. I’m going to skip this part, just know that I have assembled a data structure that looks like this:
> head(aapl.InputTrain)
RSI MACD WILL CCI FastK FastD
2008-01-02 58.36033 2.6820490 12322.21 -139.27736 -2.395499 -2.425927
2008-01-03 58.45951 2.5198403 12402.07 -103.21894 -2.453779 -2.430496
2008-01-04 41.05470 1.7483382 12482.15 -18.18663 -2.482354 -2.443877
2008-01-07 39.02805 1.0192576 12480.67 -81.05892 -2.436880 -2.457671
2008-01-08 34.20634 0.1601212 12560.93 -12.51535 -2.504909 -2.474715
2008-01-09 43.75133 -0.1721107 12641.36 -17.62074 -2.513618 -2.485136
>
And my data is split into a “train” and a “validate” time period. These are various technical indicators on AAPL stock. Ultimately, I’d like my neural network to predict tomorrow’s stock return, so my output (or “target”) is AAPL’s return tomorrow.
BUILD & TRAIN THE NEURAL NETWORK
As I mentioned, this is very easy. The function call looks exactly like a linear regression:
aapl.fit = nnet( as.matrix(Lag(aapl.rTrain,1)) ~ RSI + MACD + WILL + CCI + FastK + FastD,
data=as.matrix(aapl.InputTrain), maxit=1000, size=12, decay=0.02, linout=1 )
It is suggested that you actually build and train numerous NNs, varying the size and decay, and keep the best one. This helps find the optimal hidden layer to process your data, but I just ran this one.
Using plotnet()
from the NeuralNetTools
package, we can visualize this network, which is always super sexy.

TEST A STRATEGY
From here we can test a strategy using this neural network. Let’s keep is super simple. If our network predicts a positive return, let’s go long, a negative return, let’s go short. First, however, we need to have predicted values:
aapl.ValidateFit = predict( aapl.fit, newdata=as.matrix(aapl.rValidate) )
Then, run the strategy:
inout = 0
for(t in 2:length(aapl.rValidate[,1])){
if(aapl.ValidateFit[t-1] > 0){
inout[t] = 1
} else if(aapl.ValidateFit[t-1] < 0){
inout[t] = -1
} else {
inout[t] = 0
}
}
strategy.return = inout * aapl.r["2013::2017"]
And, now we can visualize how well the strategy works:
Looks like a terrible strategy!! Especially when compared to buy-and-hold of AAPL over the same period! Interestingly, it looks like the predictive value of the network quickly erodes.
CLOSING THOUGHTS
Let’s not be too dismissive just because our first iteration didn’t work. The fact that I could build, train, and predict using a NN in just two function calls seems pretty powerful to me. If nothing else, it is handy to use as a quick idea tester before launching into a much more in-depth NN build.
I am genuinely interested in a more expert view on the package—when and how is it best used? What are the optimal “decay” and “size” parameters?
EDIT:
I spent some noodling time with this, and I was able to generate a positive return, though it was not as high as the buy-and-hold strategy. Interestingly, the size of the hidden layer made little difference, but the decay value is what moved the needle in a serious way. Changing from 0.03 to 0.50 changed the return profile from negative to positive:
I did a little digging and found out why this may be: https://papers.nips.cc/paper/563-a-simple-weight-decay-can-improve-generalization.pdf
I should also note that neural nets are considerably better at categorization questions rather than questions of gradient. Attempting to predict the returns on a stock is not a good use of neural nets. We may have more success predicting the class of return (i.e. positive or negative). I’ll look to do a later post exploring this.