Public
Edited
May 8, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
ETH-USD@3.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
// Uncomment to activate

data_forAroundOneYear = aq
.from(data_initial)
.filter(aq.escape((d) => d["Date"].getFullYear() > 2022))
.objects()
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.barY(data_forAroundOneYear, {
x: "Date",
y1: "Open",
y2: "Close"
}),
Plot.ruleX(data_forAroundOneYear, {
x: "Date",
y1: "High",
y2: "Low"
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.barY(data_forAroundOneYear, {
x: "Date",
y1: "Open",
y2: "Close",
fill: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
}),
Plot.ruleX(data_forAroundOneYear, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
nice: true,
// candle body
marks: [
Plot.ruleX(data_forAroundOneYear, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: 4,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
}),
// wicks
Plot.ruleX(data_forAroundOneYear, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof time = interval([2017, 2023], {
step: 1,
value: [2017, 2018],
label: "Year"
})
Insert cell
// Uncomment to enable
data_filtered = aq
.from(data_initial)
.filter(aq.escape((d) => d["Date"] > earliestYear_slider_asTime))
.filter(aq.escape((d) => d["Date"] < latestYear_slider_asTime))
.objects()
Insert cell
Insert cell
Insert cell
Plot.plot({
nice: true,
width: 1100,
// candle body
marks: [
Plot.ruleX(data_filtered, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: 3,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
}),
// wicks
Plot.ruleX(data_filtered, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
numberOfDaysInFilteresData = data_filtered.length
Insert cell
Insert cell
Insert cell
Plot.plot({
nice: true,
width: 1100,
// candle body
marks: [
Plot.ruleX(data_filtered, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: (d) => 1000 / numberOfDaysInFilteresData,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
}),
// wicks
Plot.ruleX(data_filtered, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
import {Plot} from "@mkfreeman/plot-tooltip"
Insert cell
Insert cell
Plot.plot({
nice: true,
width: 1100,
// candle body
marks: [
Plot.ruleX(data_filtered, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: (d) => 1000 / numberOfDaysInFilteresData,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
title: (d) =>
`${d["Date"].toLocaleString("default", { month: "long" })} ${d[
"Date"
].getDate()}
Close: ${d3.format(".3s")(d["Close"])}
Open: ${d3.format(".3s")(d["Open"])}
High: ${d3.format(".3s")(d["High"])}
Low: ${d3.format(".3s")(d["Low"])}`
}),
// wicks
Plot.ruleX(data_filtered, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
// Uncomment the first block to enable

createTooltipContent = (d) =>
`${ d["Date"].toLocaleString('default', { month: 'long' }) } ${d["Date"].getDate()}
Close: ${ d3.format('.3s')(d["Close"]) }
High: ${ d3.format('.3s')(d["High"]) }
Open: ${ d3.format('.3s')(d["Open"]) }
Low: ${ d3.format('.3s')(d["Low"]) }`


// The same function created with classic fuction syntax:

// createTooltipContent = function (d) {
// `${ d["Date"].toLocaleString('default', { month: 'long' }) } ${d["Date"].getDate()}
// Close: ${ d3.format('.3s')(d["Close"]) }
// High: ${ d3.format('.3s')(d["High"]) }
// Open: ${ d3.format('.3s')(d["Open"]) }
// Low: ${ d3.format('.3s')(d["Low"]) }`
// }
Insert cell
Insert cell
Plot.plot({
tooltip: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
nice: true,
width: 1100,

// candle body
marks: [
Plot.ruleX(data_filtered, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: (d) => 1000 / numberOfDaysInFilteresData,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
title: (d) => createTooltipContent(d)
}),

// wicks
Plot.ruleX(data_filtered, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
fc = require('d3fc')
Insert cell
Insert cell
Insert cell
Insert cell
// Uncoment to enable

emaColumn = fc.indicatorExponentialMovingAverage()
.period( 9 )
.value(d => d["Close"])
( data_filtered )
Insert cell
Insert cell
Insert cell
// Uncoment to enable

bollingerColumn = fc.indicatorBollingerBands()
.value( d => d["Close"] )
.period( bollingerPeriod_slider )
.multiplier( 2 )
( data_filtered )
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Uncoment to enable

macdColumn = fc.indicatorMacd()
.value( d => d["Close"] )
.signalPeriod( 9 )
.fastPeriod( 12 )
.slowPeriod( 26 )
( data_filtered )
Insert cell
Insert cell
Insert cell
Insert cell
// Uncoment to enable

data_filtered_withIndicators = data_filtered.map( (d, i) => ({
ema: emaColumn[i],
macd: macdColumn[i].macd,
macdSignal: macdColumn[i].signal,
macdDivergence: macdColumn[i].divergence,
bollingerUpper: bollingerColumn[i].upper,
bollingerAverage: bollingerColumn[i].average,
bollingerLower: bollingerColumn[i].lower,
...d
}))
Insert cell
Insert cell
Inputs.table(data_filtered_withIndicators)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
tooltip: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
nice: true,
width: 1100,

// candle body
marks: [
Plot.ruleX(data_filtered_withIndicators, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: (d) => 1000 / numberOfDaysInFilteresData,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
title: (d) => createTooltipContent(d)
}),

// wicks
Plot.ruleX(data_filtered_withIndicators, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
}),

//Bollinger Band
Plot.lineY(data_filtered_withIndicators, {
x: "Date",
y: "bollingerAverage",
stroke: "dodgerBlue"
}),

//Bollinger cloud
Plot.areaY(data_filtered_withIndicators, {
x: "Date",
y1: "bollingerUpper",
y2: "bollingerLower",
fill: "dodgerblue",
fillOpacity: 0.1,
stroke: "dodgerblue",
strokeOpacity: 0.5
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
tooltip: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
nice: true,
width: 1100,

// candle body
marks: [
Plot.ruleX(data_filtered_withIndicators, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: (d) => 1000 / numberOfDaysInFilteresData,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
title: (d) => createTooltipContent(d)
}),

// wicks
Plot.ruleX(data_filtered_withIndicators, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
}),

//Bollinger Band
Plot.lineY(data_filtered_withIndicators, {
x: "Date",
y: "bollingerAverage",
stroke: "dodgerBlue"
}),

//Bollinger cloud
Plot.areaY(data_filtered_withIndicators, {
x: "Date",
y1: "bollingerUpper",
y2: "bollingerLower",
fill: "dodgerblue",
fillOpacity: 0.1,
stroke: "dodgerblue",
strokeOpacity: 0.5
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
<img src="https://alternative.me/crypto/fear-and-greed-index.png" alt="Latest Crypto Fear & Greed Index" />
Insert cell
Insert cell
// Complete the code

data_fearGreedIndex_raw = d3.json(
"https://api.alternative.me/fng/?limit=0&format=json"
)
Insert cell
Insert cell
// Uncomment to activate

data_fearGreedIndex = aq.from(data_fearGreedIndex_raw.data)
.derive({ date: aq.escape(d => new Date(+d["timestamp"] * 1000)) })
.derive({ valueAsNumber: d => +d["value"] })
.select('value_classification','date','valueAsNumber')
.rename({valueAsNumber: "FearGreedValue"})
.rename({value_classification: "FearGreedClass"})
.rename({date: "FearGreedDate"})
.objects()
Insert cell
// Uncomment to activate

data_filtered_withIndicators_withFearGreedIndex = aq.from(data_filtered_withIndicators)
.join(aq.from(data_fearGreedIndex), ["Date", "FearGreedDate"])
.objects()
Insert cell
// Uncomment to activate

Inputs.table(data_filtered_withIndicators_withFearGreedIndex)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
tooltip: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
nice: true,
width: 1100,
grid: true,
y: {
axis: "right",
label: "Price"
},

// candle body
marks: [
Plot.ruleX(data_filtered_withIndicators_withFearGreedIndex, {
x: "Date",
y1: "Open",
y2: "Close",
strokeWidth: (d) => 1000 / numberOfDaysInFilteresData,
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red"),
title: (d) => createTooltipContent(d)
}),

// wicks
Plot.ruleX(data_filtered_withIndicators_withFearGreedIndex, {
x: "Date",
y1: "High",
y2: "Low",
stroke: (d) => (d["Open"] < d["Close"] ? "Green" : "Red")
}),

//Bollinger Band
Plot.lineY(data_filtered_withIndicators_withFearGreedIndex, {
x: "Date",
y: "bollingerAverage",
stroke: "dodgerBlue"
}),

//Bollinger cloud
Plot.areaY(data_filtered_withIndicators_withFearGreedIndex, {
x: "Date",
y1: "bollingerUpper",
y2: "bollingerLower",
fill: "dodgerblue",
fillOpacity: 0.1,
stroke: "dodgerblue",
strokeOpacity: 0.5
})
]
})
Insert cell
Plot.plot({
nice: true,
height: 150,
width: 1100,
grid: true,
y: {
label: "Fear-GridValue",
axis: "right"
},
marks: [
Plot.lineY(data_filtered_withIndicators_withFearGreedIndex, {
x: "FearGreedDate",
y: "FearGreedValue",
stroke: "green"
})
]
})
Insert cell
Insert cell
Insert cell
import {toc} from "@nebrius/indented-toc"
Insert cell
import {Wrangler, op} from "@observablehq/data-wrangler"
Insert cell
import {howTo} from "@clokman/howto"
Insert cell
import {imageToDo} from "@clokman/student-blocks"
Insert cell
imageToDo
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more