Этот код представляет собой минимальное воспроизведение моей попытки раскрасить интерполированную поверхность, образованную трехмерной диаграммой рассеяния: https://codepen.io/salazarm/pen/jOWprBj
const colorScale = [
['0', 'rgb(0,0,134)'],
['0.25', 'rgb(144, 252, 227)'],
['0.5', 'rgb(170, 255, 137)'],
['0.6', 'rgb(252, 242, 57)'],
['0.72', 'rgb(232, 162, 38)'],
['1.0', 'rgb(255,0,0)']
]
const rows = [40, 60, 80, 100, 120, 140, 160, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 320, 340, 360, 400, 440, 480, 520, 560, 600, 640, 680, 720, 760, 800, 840, 880]
const columns = [0.052739649650399546, 0.12945197841527142, 0.2061643071803019, 0.4554793756714548, 0.7047944441625761]
const values = [[null, null, null, 113.806298215936, null], [null, null, 103.900929577649, 103.394281813932, null], [135.34303782888, null, 103.900929577649, 96.4973275646427, null], [108.288007618313, null, 96.9374808519993, 88.4701807557266, null], [104.806931150651, null, 89.5941932328483, 81.0825414680379, null], [104.262156815898, null, 79.1466980571445, 77.981025578435, 80.0538058935848], [89.6207952967281, 76.567630405239, 73.6338682016538, 75.5243937833531, 78.1929983961292], [78.6892837901259, 69.2653363438868, 69.5817969484183, 74.111832337461, 77.6079458081274], [71.293351459305, 65.8569996458742, 68.0180909105966, 73.5734063243125, 77.5322852147224], [65.316047859924, 62.9838274346249, 67.0338854156817, 73.163493152822, 77.5147957849701], [59.6157671081532, 60.8971725567913, 66.6950117095839, 72.9733237849779, 77.5166924729988], [55.1465270015558, 59.7339264506726, 66.6759894665981, 72.9064986987144, 77.5147957849701], [52.6725276546741, 59.4912189277008, 66.6499758394995, 72.8618164884652, 77.5013633559977], [52.2188230062308, 59.721594700194, 66.6759894665981, 72.9064986987144, 77.5147957849701], [53.02866259277, 60.027680355529, 66.8842775134721, 73.107512411912, 77.5893277994543], [56.4295083378783, 60.6570150804307, 67.3041397692378, 73.3623839123188, 77.6963876779564], [59.9360968033528, 61.8925547790689, 67.9398636688808, 73.5710625126337, 77.8237117578229], [63.6186218043185, 63.514009626044, 68.7966346073292, 73.812630437495, 78.0870750608216], [67.6258116769059, 65.2426087397014, 69.8548427173008, 74.161369209824, 78.5620296691413], [72.006223225742, 67.068902742936, 70.9947991227318, 74.4932246337334, 79.0351972222315], [79.5551153843496, 71.0841035058806, 73.197205726249, 74.9114996023901, 79.4670910856406], [86.4307015102761, 75.2126803652063, 75.4671545770312, 75.8159276839487, 79.9092718210033], [92.5723194923175, null, 77.8862376081645, 77.0097238990493, 80.2613632791949], [null, null, 82.9364788630799, 78.9515920825482, 81.1207508800967], [null, null, 87.2205084420847, 80.6484118067602, 82.0448991846857], [null, null, 90.7719613032328, 82.2187731625783, 82.5748468616411], [null, null, 94.2510493862921, 84.0224223301196, 83.7975850079844], [null, null, 96.9608162058347, 85.9512358715619, 85.2001342699325], [null, null, 99.7323836131293, 87.7804051319916, 85.9969166858732], [null, null, 101.615505349713, 89.439360691515, 86.4768217400097], [null, null, 104.207611221204, 90.9224637411827, 87.197355777999], [null, null, 104.988811665223, 92.3295586808031, 88.7160251454981], [null, null, 106.48007083975, 93.786860712374, null], [null, null, 107.865511408241, 95.4205850378931, null], [null, null, 111.099384393054, null, null], [null, null, 111.854356575734, null, null]]
const fValues = flatten(values);
const valuesNoNan = fValues.filter(val => !isNaN(val))
const min = Math.min(...valuesNoNan)
const max = Math.max(...valuesNoNan)
const diff = max - min;
const colors = fValues.map(v => (v - min) / diff);
const chart = [{
type: 'scatter3d',
mode: 'markers',
surfaceaxis: 2,
colorScale: colorScale,
marker: {
color: colors,
cMin: min,
cMax: max,
size: 5,
symbol: 'circle',
opacity: 0.8
},
connectgaps: true,
x: flatten(values.map((row, rowIndex) => row.map(() => rows[rowIndex]))),
y: flatten(values.map((row) => row.map((_, colIndex) => columns[colIndex]))),
z: fValues,
}];
const layout = {
title: 'Implied Volatility',
autosize: true,
width: 980,
height: 980,
margin: {
l: 65,
r: 50,
b: 65,
t: 90,
},
scene: {
aspectratio: { x: 1, y: 1, z: 1 }
},
xaxis: {
title: {
text: 'Strike Price',
font: {
family: 'Courier New, monospace',
size: 18,
color: '#7f7f7f'
}
},
},
yaxis: {
title: {
text: 'Time To Expiration',
font: {
family: 'Courier New, monospace',
size: 18,
color: '#7f7f7f'
}
}
}
};
Plotly.plot('graph', chart, layout);
function flatten(array) {
const result = [];
$flatten(array, result);
return result;
}
/**
* Internal flatten function recursively passes `result`.
*/
function $flatten(array, result) {
for (let i = 0; i < array.length; i++) {
const value = array[i];
if (Array.isArray(value)) {
$flatten(value, result);
} else {
result.push(value);
}
}
}
Я пробовал несколько разных вещей и искали в Google, даже читая исходный код, но я не могу понять, как раскрасить поверхность и точки в соответствии с моей цветовой шкалой.