Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active April 2, 2023 10:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dacr/07562724c8e277c96408221e2aef9d6b to your computer and use it in GitHub Desktop.
Save dacr/07562724c8e277c96408221e2aef9d6b to your computer and use it in GitHub Desktop.
Visualize DJI historical data - The (mis) behavior of markets : A fractal view of Risk, Ruin and Reward - Benoît Mandelbrot / published by https://github.com/dacr/code-examples-manager #fde7d2a2-d081-4199-8284-1f2474743040/bdefbb9e69906be11ae75dae99fd761b9ff11634
// summary : Visualize DJI historical data - The (mis) behavior of markets : A fractal view of Risk, Ruin and Reward - Benoît Mandelbrot
// keywords : scala, stocks, data, dji, visualize, graph, plotly, mandelbroot, fractal
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : fde7d2a2-d081-4199-8284-1f2474743040
// created-on : 2021-01-30T21:19:17Z
// managed-by : https://github.com/dacr/code-examples-manager
// execution : scala ammonite script (http://ammonite.io/) - run as follow 'amm scriptname.sc'
import $ivy.`com.github.pathikrit::better-files:3.9.1`
import $ivy.`org.json4s::json4s-jackson:3.6.10`
import $ivy.`org.json4s::json4s-ext:3.6.10`
import $ivy.`org.plotly-scala::plotly-render:0.8.2`
import better.files._
import org.json4s._
import org.json4s.ext.{JavaTimeSerializers, JavaTypesSerializers}
import org.json4s.jackson.JsonMethods.parse
import plotly._
import element._
import layout._
import Plotly._
import scala.math._
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import scala.util.Properties.envOrNone
implicit val chosenFormats = DefaultFormats.lossless ++ JavaTimeSerializers.all ++ JavaTypesSerializers.all
val djiFile = envOrNone("TMBOM_DJI_JSON").getOrElse("tmbom_dji.json").toFile
val dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd")
case class Entry(date: LocalDate, open: Double, high: Double, low: Double, close: Double, volume: Option[Long]) {
val fdate = dateFormat.format(date)
}
case class Cell(date: String, value: Double)
val entries = {
djiFile
.lineIterator
.to(LazyList)
.map(line => parse(line).extract[Entry])
}
// ------------------------------------------------------------------------------------
def sign(x: Double) = if (x < 0) -1d else 1d
//def symLog(x:Double) = sign(x)*(log10(1+abs(x) / 0.3d))
def symLog(x: Double) = sign(x) * (log10(1 + abs(x)/10))
// https://www.mathworks.com/matlabcentral/fileexchange/57902-symlog
// http://blog.originlab.com/visualizing-the-negative-log
def variation(a:Entry, b:Entry) = b.close - a.close
def variationPercent(a:Entry, b:Entry) = (b.close - a.close)/b.close*100d
val closings = entries.map(e => Cell(e.fdate, e.close))
//val deltas = entries.sliding(2, 1).map { case LazyList(a, b) => Cell(b.fdate, variation(a,b)) }.to(LazyList)
val deltas = entries.sliding(2, 1).map { case LazyList(a, b) => Cell(b.fdate, variationPercent(a,b)) }.to(LazyList)
// Trying a symlog compute as plotly Log scale doesn't support "negatives" values
val symLogDeltas = entries.sliding(2, 1).map { case LazyList(a, b) => Cell(b.fdate, symLog(variationPercent(a,b))) }.to(LazyList)
val data = Seq(
Scatter(closings.map(_.date), closings.map(_.value))
.withName("DJI"),
Scatter(deltas.map(_.date), deltas.map(_.value))
.withName("day to day variations")
.withLine(Line().withColor(Color.RGBA(50, 50, 50, 0.25)))
.withYaxis(AxisReference.Y2),
)
val dataSymLog = Seq(
Scatter(closings.map(_.date), closings.map(_.value))
.withName("DJI"),
Scatter(symLogDeltas.map(_.date), symLogDeltas.map(_.value))
.withName("day to day variations")
.withLine(Line().withColor(Color.RGBA(50, 50, 50, 0.25)))
.withYaxis(AxisReference.Y2),
)
val classicLayout =
Layout()
.withHeight(800)
.withWidth(1600)
.withYaxis(
Axis()
.withTitle("DJI closing")
.withAutorange(true)
.withSide(Side.Left))
.withTitle("Dow Jones Historical Analysis")
.withYaxis2(
Axis()
.withTitle("DJI day to day variation")
.withAutorange(true)
.withOverlaying(AxisAnchor.Y)
.withSide(Side.Right)
)
val logLayout =
Layout()
.withHeight(800)
.withWidth(1600)
.withYaxis(
Axis()
.withTitle("DJI closing")
.withAutorange(true)
.withSide(Side.Left)
.withType(AxisType.Log)
)
.withTitle("Dow Jones Historical Analysis (logarithmic)")
.withYaxis2(
Axis()
.withTitle("DJI day to day variation")
.withAutorange(true)
.withSide(Side.Right)
.withOverlaying(AxisAnchor.Y)
//.withType(AxisType.Log) // SHIT PLOTLY DOESN'T SUPPORT SYMLOG !!!! :(
)
plot("plot-classic.html", data, classicLayout, openInBrowser = true, addSuffixIfExists = true)
plot("plot-logarithmic.html", dataSymLog, logLayout, openInBrowser = true, addSuffixIfExists = true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment