blob: 238f83b1f3f082b776b5e2ca2d4dd16e2402e582 [file] [log] [blame]
package io.prediction.examples.stock_old
import io.prediction.controller.LAlgorithm
import io.prediction.controller.EmptyParams
import io.prediction.controller.IEngineFactory
import io.prediction.controller.SimpleEngine
import breeze.linalg.{ DenseMatrix, DenseVector }
import breeze.stats.{ mean, meanAndVariance }
import com.github.nscala_time.time.Imports._
import nak.regress.LinearRegression
import org.saddle._
import org.saddle.index.IndexTime
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.{ Map => MMap }
import scala.math
object RegressionEngineFactory extends IEngineFactory {
def apply() = {
new SimpleEngine(classOf[StockDataSource], classOf[RegressionAlgorithm])
}
}
class RegressionAlgorithm
extends StockAlgorithm[EmptyParams, Map[String, DenseVector[Double]]] {
//extends LAlgorithm[EmptyParams, TrainingData, Map[String, DenseVector[Double]],
//Query, Target] {
private def getRet(logPrice: Frame[DateTime, String, Double], d: Int) =
(logPrice - logPrice.shift(d)).mapVec[Double](_.fillNA(_ => 0.0))
private def regress(
ret1d: Series[DateTime, Double],
ret1w: Series[DateTime, Double],
ret1m: Series[DateTime, Double],
retF1d: Series[DateTime, Double]) = {
val array = (
Seq(ret1d, ret1w, ret1m).map(_.toVec.contents).reduce(_ ++ _) ++
Array.fill(ret1d.length)(1.0))
val target = DenseVector[Double](retF1d.toVec.contents)
val m = DenseMatrix.create[Double](ret1d.length, 4, array)
val result = LinearRegression.regress(m, target)
result
}
// Build a linear model
// ret(-1) = a * ret_1d + b * ret_1w + c * ret_1m + d
def train(trainingData: TrainingData): Map[String, DenseVector[Double]] = {
val price = trainingData.priceFrame
val logPrice = price.mapValues(math.log)
val ret1d = getRet(logPrice, 1)
val ret1w = getRet(logPrice, 5)
val ret1m = getRet(logPrice, 22)
val retF1d = getRet(logPrice, -1)
val timeIndex = price.rowIx
val firstIdx = 25
val lastIdx = timeIndex.length
val tickers = price.colIx.toVec.contents
val tickerModelMap = tickers.map(ticker => {
val model = regress(
ret1d.firstCol(ticker).slice(firstIdx, lastIdx),
ret1w.firstCol(ticker).slice(firstIdx, lastIdx),
ret1m.firstCol(ticker).slice(firstIdx, lastIdx),
retF1d.firstCol(ticker).slice(firstIdx, lastIdx))
(ticker, model)
}).toMap
tickerModelMap
}
private def predictOne(
coef: DenseVector[Double],
price: Series[DateTime, Double]): Double = {
val shifts = Seq(0, 1, 5, 22)
val sp = shifts
.map(s => (s, math.log(price.raw(price.length - s - 1))))
.toMap
val vec = DenseVector[Double](
sp(0) - sp(1),
sp(0) - sp(5),
sp(0) - sp(22),
1)
val p = coef.dot(vec)
return p
}
def predict(model: Map[String, DenseVector[Double]], query: Query)
: Target = {
val price: Frame[DateTime, String, Double] = query.priceFrame
val prediction = price.colIx.toVec.contents
// If model doesn't have the data, skip
.filter { ticker => model.contains(ticker) }
.filter { _ != query.mktTicker }
.map { ticker =>
{
val p = predictOne(
model(ticker),
price.firstCol(ticker))
(ticker, p)
}
}.toMap
new Target(date = query.tomorrow, data = prediction)
}
}