Elliott Wave Visualization in Generative Art
written by reyrove
Setting the Stage
The code starts by determining the dimensions of the canvas, which will be a square of size e
, dynamically set based on the smaller of the screen's width and height.
const e = Math.min(innerWidth, innerHeight);
const canvas = { w: e, h: e };
const features = {};
Setting Up the Canvas
The setup()
function initializes the canvas with a white background and ensures the visualization is drawn only once, by calling noLoop()
. It also triggers the drawElliottWaves()
function to generate the visual.
function setup() {
createCanvas(e, e);
background(255);
noLoop();
drawElliottWaves();
const readableFeaturesObj = {};
console.table(readableFeaturesObj);
$fx.features(readableFeaturesObj);
}
Elliott Wave Generation
The core of this code lies in the drawElliottWaves()
function, which generates the Elliott Wave pattern. We first calculate several key variables, such as the number of days (360), the number of weeks, and the number of months. These values help in scaling the width and height of the waves appropriately.
function drawElliottWaves() {
let wavePoints = [];
let numDays = 360;
let numWeeks = Math.floor(numDays / 7);
let numMonths = Math.ceil(numDays / 30);
let fixedGap = e / 10;
let totalWaveWidth = e - 2 * fixedGap;
let waveHeight = e/25;
let waveWidth = totalWaveWidth / numDays;
let x = fixedGap;
let y = height / 2;
Generating Randomized Wave Points
For each of the 360 days, we randomly vary the direction of the wave and its height, adding some chaotic yet controlled variation to emulate the unpredictability of real market movements. We then calculate the range for the y-axis values and store these points in an array for further processing.
for (let i = 0; i < numDays; i++) {
let direction = (i % 2 === 0) ? random(-1, 0) : random(0, 1);
y += direction * waveHeight * (0.8 + $fx.rand() * 0.4);
wavePoints.push({ x: x, y: y });
x += waveWidth * (0.8 + $fx.rand() * 0.4);
}
Drawing the Waves
Once the points are generated, we pass them to the drawWaves()
function. This function simply connects the points using lines, creating the visual representation of the Elliott Waves.
function drawWaves(points) {
stroke(0);
strokeWeight(2);
for (let i = 0; i < points.length - 1; i++) {
line(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
}
}
Adding Candlesticks
To enhance the visualization, we include weekly candlesticks, a common feature in stock charts. These candlesticks represent open, close, high, and low prices for each week, further adding depth to the visual. Depending on whether the closing price is higher or lower than the opening price, the candlestick will be green (up) or red (down).
function drawCandlesticks(points, numDays, numWeeks, fixedGap, totalWaveWidth) {
strokeWeight(1);
let weekWidth = totalWaveWidth / numWeeks;
for (let i = 0; i < numDays - 1; i += 7) {
let startIndex = i;
let endIndex = min(i + 7, points.length - 1);
let open = points[startIndex].y + $fx.rand() * 40 - 20;
let close = points[endIndex].y + $fx.rand() * 40 - 20;
let high = Math.min(open, close) - $fx.rand() * 10 - 10;
let low = Math.max(open, close) + $fx.rand() * 10 + 10;
let colorFill = (close < open) ? color(255, 0, 0) : color(0, 255, 0);
let weekStartX = fixedGap + (i / numDays) * totalWaveWidth;
let weekEndX = fixedGap + ((i + 7) / numDays) * totalWaveWidth;
let candleWidth = e / 300;
let candleCenterX = (weekStartX + weekEndX) / 2;
stroke(colorFill);
line(candleCenterX, high, candleCenterX, low);
fill(colorFill);
stroke(colorFill);
strokeWeight(1);
rectMode(CENTER);
rect(candleCenterX, (open + close) / 2, candleWidth, abs(open - close));
}
}
Adding Monthly and Y-Axis Labels
The monthly axis is drawn at the bottom of the canvas, showing the months' names for easy navigation. Additionally, a Y-axis with ticks and labels is added to help visualize the price range, ensuring that the wave chart is both informative and aesthetically pleasing.
function drawMonthlyAxis(numDays, fixedGap, totalWaveWidth) {
stroke(150);
strokeWeight(1);
let monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
let numMonths = monthNames.length;
let monthWidth = totalWaveWidth / numMonths;
for (let i = 0; i < numMonths; i++) {
let monthX = fixedGap + (i / numMonths) * totalWaveWidth;
line(monthX, 0, monthX, height);
textSize(10);
textAlign(CENTER, TOP);
fill(0);
text(monthNames[i], monthX, height - 20);
}
}
function drawYAxis(minY, maxY) {
stroke(150);
strokeWeight(1);
let yAxisX = e / 10;
let numTicks = 10;
let tickSpacing = height / numTicks;
line(yAxisX, 0, yAxisX, height);
for (let i = 0; i <= numTicks; i++) {
let yPos = height - (i * tickSpacing);
let labelValue = map(i, 0, numTicks, minY, maxY);
stroke(150);
line(yAxisX - 5, yPos, yAxisX + 5, yPos);
textSize(10);
textAlign(RIGHT, CENTER);
fill(0);
text(nf(labelValue, 1, 2), yAxisX - 10, yPos);
}
}
Wrapping Up
The resulting chart is a beautifully chaotic yet structured representation of Elliott Wave theory. It combines elements of technical analysis with generative art principles, transforming financial data into a stunning, informative visual experience.
Applications
This generative artwork is not just a static piece; it's a dynamic, evolving dataset that serves multiple purposes:
- AI Training : The visual data produced is ideal for training AI models in market behavior, prediction, and analysis.
- Financial Analysis : The generated patterns and candlestick data can be used to explore and understand market dynamics in a unique way.
- Artistic Expression : Each iteration of the code creates a visually compelling representation of market theory, bridging the gap between art and science, transforming financial concepts into digital poetry.
Conclusion
In this project, the randomness integrated into the artwork serves as a crucial component in emulating the behavior of financial markets. The result is a dynamic and evolving piece that not only stands as a visual masterpiece but also as a sophisticated dataset, ready to be used in AI-driven marketing strategies, financial analysis, and beyond. This makes the project a perfect blend of creative expression and cutting-edge technology.
Play with the code, unleash your creativity, and explore the fascinating intersection of finance and art. For the full code, click here ✨💻.
With love, endless imagination, and a touch of finance, by Frostbond Coders 🎨📈