The prediction window is the number of prior days that the neural network uses to make a bullish or bearish determination. The bull/bear window is the number of days forward that the network will look to decide if the previous window should be considered an indication of a bull or bearish period. For example, if you choose 30 days as the bull/bear period, that period will be bullish if the security price rises above the bullish percent, or bearish if it falls below the bearish percent. As the program looks over the date range, it creates many training examples of prediction windows that resulted in either a bullish or bearish period.
Once the data has been gathered, the neural network can be trained. While gathering data is relatively quick, training can be very slow. A neural network is made up of layers. Data is fed to the input layer and predictions come from the output layer. There are also hidden layers between the input and output layers. The following diagram shows a simple neural network.
The network is made up of connections between the neurons. The training process adjusts those connections so that the inputs produce the desired outputs. Training is an iterative process. To begin training select the "Train" item from the "Neural Network" menu. The training will begin. You will see an error percent. The goal is to try to minimize that. If it never minimizes much then the data you entered for gathering is not conducive to determining patterns. Training can go on for hours or days. Once you are done training you can click the button to stop the training. Your neural network is now ready to predict.
Enter a stock symbol and starting date at the top of the window and click "Chart/Predict". You will see something similar to the following.
Here you see one segment of time. The neural network shows its predictions by the red or green bars. Red indicates bearish sentiment, whereas green is bulish. The above chart shows a time slice of Apple Computer being predicted with a neural network trained on GE. The decision for these two was purely arbitrary. GE is very representative of the broader market so I often use it as a baseline. Ideally you would pick a handful of companies to form the baseline, this would be a good enhancement to this program.
You can see above that the program started to get bullish about apple just as the upward trend began. Then the program became neutral as it leveled. Two bearish lines were draw as it began to drop again. It is not always this accurate. But this demonstrates the type of data it returns.
Implementing the Application
This application makes use of Encog. Encog is an open source neural network framework released under the Lesser GNU Public License (LGPL). There are versions of Encog available for Java, .Net, and Silverlight. Encog is hosted at Google Code. Download links, as well as more information on Encog can be found at the following URL:
The application must create training data for the neural network. This training data is gathered by the GatherUtil class included as part of the program. This is the class that you would modify to enhance the training strategy. It is used both to create training data for a large block of data, as well as querying the neural network for a prediction. We will first examine how the training data is generated. It is generated in a method called LoadCompany. This method begins by creating a YahooFinanceLoader. The YahooFinanceLoader is provided by Encog.
IMarketLoader loader = new YahooFinanceLoader();
TickerSymbol ticker = new TickerSymbol(symbol);
We must create a list to tell Encog what market data we are interested in. We are using the close, open, high and low values for each day. We are only using the actual candlestick data. To keep this example simple, we are also not using volume. Volume, however, can be very useful for predicting trends and is often considered in different disciplines.
IList<MarketDataType> dataNeeded = new List<MarketDataType>();
All of the requested is then loaded into a large list and sorted.
List<LoadedMarketData> results = (List<LoadedMarketData>)loader.Load(ticker, dataNeeded, from, to);
Bullish or Bearish Trend
We will now loop over all of the data and build training elements. We need to peek backwards from the present day over the prediction window. So we begin our loop far enough into the list to have at least one prediction window to look back on. We end just short of an evaluation window. The evaluation window is used to determine if a bullish or bearish trend started after the prediction window.
for (int index = PredictWindow; index < results.Count - EvalWindow; index++)
The market data is obtained and we create two flags to determine if this is a bullish or bearish region of the chart.
LoadedMarketData data = results[index];
// determine bull or bear position, or neither
bool bullish = false;
bool bearish = false;
To make the bullish or bearish determination we loop over the evaluation period and look at the percent changes.
for (int search = 1; search <= EvalWindow; search++)
LoadedMarketData data2 = results[index + search];
double priceBase = data.GetData(MarketDataType.ADJUSTED_CLOSE);
double priceCompare = data2.GetData(MarketDataType.ADJUSTED_CLOSE);
double diff = priceCompare - priceBase;
double percent = diff / priceBase;
If the percent change is greater than the bullish percent, then this is a bullish region. Otherwise it is bearish.
if (percent > BullPercent)
bullish = true;
else if (percent < BearPercent)
bearish = true;
Now that we know if this region was bullish or bearish we can create training data. If it was neither bullish nor bearish, no training data will be created. We do not use the entire chart for training.
INeuralDataPair pair = null;
pair = CreateData(results, index, true);
else if (bearish)
pair = CreateData(results, index, false);
If a training pair was created, add it to the Encog training data.
if (pair != null)
You will notice above that a method called CreateData was called to create the input data to the neural network. This method is used both to generate the input side of the training pair, as well as to create input to the neural network for a prediction. This method looks at the evaluation window and creates the input to the neural network. This very important function is analyzed here.
This function begins by creating a BasicNeuralData object. This is what Encog uses for all neural network input and output. There are 14 elements. These correspond to the 14 basic candlestick patterns seen earlier. We are going to use a very simple pattern. We are simply going to sum up the number of each of the 14 candlestick patterns. This is a very simple way to do this, but it can produce some good results. To do something more advanced just think about how you want to represent the evaluation window to the neural network as an array of floating point numbers. The input and output to a neural network is always an array of floating point numbers.
Another advantage to this very simple approach is the candlesticks are atomic. We are only considering the movement on a given day. We are not considering the actual price change day-to-day. This means the code does not need to worry about stock-splits. This removes another layer of complexity from the neural network. When I compare day-to-day I need to make use of the "adjusted close" field, which informs me of stock splits.
INeuralData neuralData = new BasicNeuralData(14);
int totalPatterns = 0;
int patternCount = new int;
We begin by looping over the entire evaluation window.
for (int i = 0; i < EvalWindow; i++)
LoadedMarketData data = marketData[(marketDataIndex-EvalWindow) + i];
We use the provided IdentifyCandleStick class to determine what sort of a candlestick this is.
IdentifyCandleStick candle = new IdentifyCandleStick();
int pattern = candle.DeterminePattern();
The pattern variable now holds a value, between zero and thirteen that indicates what candlestick this was. We keep count of each type.
if (pattern != IdentifyCandleStick.UNKNOWN)
Not every possible combination of shadow and body produces a named candlestick. If there were no named candlesticks in the entire evaluation window, then it will not be considered.
if (totalPatterns == 0)
The input and output floating point numbers for a neural network are usually between zero and one. To accommodate this we represent each o the 14 candlestick patterns as a percent. These are the 14 input neurons.
for (int i = 0; i < 14; i++)
neuralData[i] = ((double)patternCount[i]) / ((double)totalPatterns);
The neural network is trained to accept the above input and produce a 0.9 for bullish, a 0.1 for bearish. When we use the network for prediction we will feed the average number of candlesticks into the network and use the output to make a forecast. We consider an output of .8 or higher to be bullish, a 0.2 or lower to be bearish, and anything in-between means the network is neutral on the current day.
This article served as a very simple introduction to using neural networks to assist in technical market analysis. It should not be used as a starting point for exploring other technical or fundamental strategies you may wish to explore. Areas for further exploration are volume, day-to-day price changes, and better representing the patterns presented to the neural network. For more information about Encog, and other examples, visit the Encog homepage at http://www.heatonresearch.com/encog