"<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BTCUSDC Live Moving Average, Standard Deviation, and Derivatives with Trading Simulation</title>
<!-- Include Chart.js (Latest Version) -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- Include Chart.js Zoom Plugin (Latest Version) -->
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
</head>
<body>
<h1>BTCUSDC Live Moving Average, Standard Deviation, and Derivatives with Trading Simulation</h1>
<canvas id="chart" width="800" height="400"></canvas>

<script>
let chart; // Global variable for the chart
let dataFetchInterval; // Interval variable for data fetching

// Function to initialize the default behavior on page load
window.onload = function() {
    main();
    // Set interval to update data every minute (60000 milliseconds)
    dataFetchInterval = setInterval(main, 60000);
};

async function main() {
    // Fetch data from 8 hours ago to now
    const endTime = new Date().getTime(); // Current time
    const startTime = endTime - (120 * 60 * 60 * 1000); // 8 hours ago

    // Fetch BTCUSDC 1-minute prices from Binance API
    const symbol = 'BTCUSDC';
    const interval = '1m';

    const klines = await fetchKlines(symbol, interval, startTime, endTime);

    if (klines.length === 0) {
        alert('No data available for the selected date range.');
        return;
    }

    // Extract closing prices and timestamps
    const timestamps = klines.map(k => k[0]); // Open time
    const closePrices = klines.map(k => parseFloat(k[4])); // Close price

    // Calculate Moving Averages and Standard Deviation
    const ma99 = movingAverage(closePrices, 99);
    const ma7 = movingAverage(closePrices, 7);
    const stdDev99 = movingStandardDeviation(closePrices, 199);

    // Calculate first derivative of MA99
    const derivative = firstDerivative(ma99);

    // Calculate second derivative of MA99
    const secondDerivative = firstDerivative(derivative);

    // Calculate MA99 of the derivative
    const ma99Derivative = movingAverage(derivative, 99);

    // Calculate derivative of MA99 derivative
    const derivativeOfMA99Derivative = firstDerivative(ma99Derivative);

    // The earliest index where all data arrays have valid data
    const startingIndex = 198;

    // Prepare data for plotting
    const labels = timestamps.slice(startingIndex).map(ts => new Date(ts).toLocaleString());
    const priceData = closePrices.slice(startingIndex);
    const ma99Data = ma99.slice(startingIndex);
    const ma7Data = ma7.slice(startingIndex);
    const stdDev99Data = stdDev99.slice(startingIndex);
    const derivativeData = derivative.slice(startingIndex);
    const secondDerivativeData = secondDerivative.slice(startingIndex);
    const ma99DerivativeData = ma99Derivative.slice(startingIndex);
    const derivativeOfMA99DerivativeData = derivativeOfMA99Derivative.slice(startingIndex);

    // Simulate trading strategy
    const {specialPointsData, tradeSignals, totalAssetValueData} = simulateTrading(
        priceData,
        derivativeData,
        secondDerivativeData,
        derivativeOfMA99DerivativeData,
        ma99Data,stdDev99Data,ma7Data
    );

    // Plot or update the data
    plotData(
        labels,
        priceData,
        ma99Data,
        derivativeData,
        secondDerivativeData,
        ma99DerivativeData,
        derivativeOfMA99DerivativeData,
        specialPointsData,
        totalAssetValueData,
        ma7Data,
        stdDev99Data
    );
}

async function fetchKlines(symbol, interval, startTime, endTime) {
    const limit = 1000; // Max limit per request
    let klines = [];
    let fetchTime = startTime;

    while (fetchTime < endTime) {
        const url = `https://fapi.binance.com/fapi/v1/klines?symbol=${symbol}&interval=${interval}&startTime=${fetchTime}&endTime=${endTime}&limit=${limit}`;

        const response = await fetch(url);
        const data = await response.json();

        if (data.code) {
            // Handle error
            alert('Error fetching data: ' + data.msg);
            break;
        }

        if (data.length === 0) {
            break;
        }

        klines = klines.concat(data);
        fetchTime = data[data.length - 1][0] + 60000; // Next minute
    }

    return klines;
}

function movingAverage(data, windowSize) {
    let ma = [];
    for (let i = 0; i < data.length; i++) {
        if (i < windowSize - 1 || data[i] === null) {
            ma.push(null); // Not enough data to calculate MA
        } else {
            const windowData = data.slice(i - windowSize + 1, i + 1);
            if (windowData.includes(null)) {
                ma.push(null); // Moving average cannot be calculated with null values
            } else {
                const sum = windowData.reduce((acc, val) => acc + val, 0);
                ma.push(sum / windowSize);
            }
        }
    }
    return ma;
}

function movingStandardDeviation(data, windowSize) {
    let stdDev = [];
    for (let i = 0; i < data.length; i++) {
        if (i < windowSize - 1 || data[i] === null) {
            stdDev.push(null); // Not enough data to calculate
        } else {
            const windowData = data.slice(i - windowSize + 1, i + 1);
            if (windowData.includes(null)) {
                stdDev.push(null);
            } else {
                const mean = windowData.reduce((acc, val) => acc + val, 0) / windowSize;
                const variance = windowData.reduce((acc, val) => acc + Math.pow(val - mean,2), 0) / windowSize;
                stdDev.push(Math.sqrt(variance));
            }
        }
    }
    return stdDev;
}

function firstDerivative(data) {
    let derivative = [];
    for (let i = 0; i < data.length; i++) {
        if (i === 0 || data[i - 1] === null || data[i] === null) {
            derivative.push(null); // Cannot calculate derivative
        } else {
            derivative.push(data[i] - data[i - 1]);
        }
    }
    return derivative;
}

function simulateTrading(priceData, derivativeData, secondDerivativeData, derivativeOfMA99DerivativeData, ma99Data,std,ma7) {
    let specialPointsData = [];
    let tradeSignals = [];
    let position = 0; // BTC holdings
    let cash = 500; // USDC balance (we start with 500 USDC)
    let totalAssetValueData = []; // Total value of assets over time in USDC

    for (let i = 0; i < priceData.length; i++) {
        // Buy condition with new criterion
        if (
            derivativeData[i] !== null &&
            secondDerivativeData[i] !== null &&
            derivativeOfMA99DerivativeData[i] !== null &&
            derivativeData[i] < -std[i]/50 &&
            secondDerivativeData[i] > 0 &&
            derivativeOfMA99DerivativeData[i] < -std[i]/2500 &&
            ma99Data[i] > priceData[i]&&priceData[i]>ma7[i]
        ) {
            // Buy signal
            if (position === 0 && cash >= 50) {
                // Buy BTC worth 50 USDC
                let btcBought = 50 / (priceData[i] * 1.0006); // Include 0.06% fee
                position += btcBought;
                cash -= 50; // We spend 50 USDC
                tradeSignals.push({type: 'buy', index: i, price: priceData[i]});
            }
            specialPointsData.push(priceData[i]); // Mark special point
        } else {
            specialPointsData.push(null);
        }

        // Sell condition
        if (position > 0 && priceData[i] > ma99Data[i]) {
            // Sell all BTC holdings
            let proceeds = position * (priceData[i] * 0.9994); // Include 0.06% fee
            cash += proceeds;
            position = 0; // Reset position

            tradeSignals.push({type: 'sell', index: i, price: priceData[i]});
        }

        // Update total asset value
        let totalAssetValue = cash + position * priceData[i];
        totalAssetValueData.push(totalAssetValue);
    }

    return {specialPointsData, tradeSignals, totalAssetValueData};
}

function plotData(labels, priceData, ma99Data, derivativeData, secondDerivativeData, ma99DerivativeData, derivativeOfMA99DerivativeData, specialPointsData, totalAssetValueData, ma7Data, stdDev99Data) {
    const ctx = document.getElementById('chart').getContext('2d');

    // Create an array of zeros for the zero line
    const zeroData = labels.map(() => 0);

    if (!chart) {
        // Initial chart creation
        chart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: labels,
                datasets: [
                    {
                        label: 'Actual Price',
                        data: priceData,
                        borderColor: 'black',
                        fill: false,
                        yAxisID: 'y',
                        pointRadius: 0,
                    },
                    {
                        label: 'Moving Average (99)',
                        data: ma99Data,
                        borderColor: 'blue',
                        fill: false,
                        yAxisID: 'y',
                        pointRadius: 0,
                    },
                    {
                        label: 'Moving Average (7)',
                        data: ma7Data,
                        borderColor: 'orange',
                        fill: false,
                        yAxisID: 'y',
                        pointRadius: 0,
                    },
                    {
                        label: 'Standard Deviation (99)',
                        data: stdDev99Data,
                        borderColor: 'brown',
                        fill: false,
                        yAxisID: 'y3',
                        pointRadius: 0,
                    },
                    {
                        label: 'First Derivative',
                        data: derivativeData,
                        borderColor: 'green',
                        fill: false,
                        yAxisID: 'y1',
                        pointRadius: 0,
                    },
                    {
                        label: 'Second Derivative',
                        data: secondDerivativeData,
                        borderColor: 'red',
                        fill: false,
                        yAxisID: 'y1',
                        pointRadius: 0,
                    },
                    {
                        label: 'Derivative Zero Line',
                        data: zeroData,
                        borderColor: 'gray',
                        borderDash: [5, 5],
                        pointRadius: 0,
                        borderWidth: 1,
                        fill: false,
                        yAxisID: 'y1',
                    },
                    {
                        label: 'MA99 of Derivative',
                        data: ma99DerivativeData,
                        borderColor: 'magenta',
                        fill: false,
                        yAxisID: 'y1',
                        pointRadius: 0,
                    },
                    {
                        label: 'Derivative of MA99 of Derivative',
                        data: derivativeOfMA99DerivativeData,
                        borderColor: 'cyan',
                        fill: false,
                        yAxisID: 'y1',
                        pointRadius: 0,
                    },
                    {
                        label: 'Special Points (Buy Signal)',
                        data: specialPointsData,
                        borderColor: 'purple',
                        backgroundColor: 'purple',
                        pointRadius: 5,
                        pointHoverRadius: 7,
                        showLine: false,
                        yAxisID: 'y',
                        type: 'line',
                    },
                    {
                        label: 'Total Asset Value',
                        data: totalAssetValueData,
                        borderColor: 'darkorange',
                        fill: false,
                        yAxisID: 'y2',
                        pointRadius: 0,
                        borderWidth: 2,
                        tension: 0.1,
                    },
                ]
            },
            options: {
                responsive: true,
                interaction: {
                    mode: 'index',
                    intersect: false,
                },
                stacked: false,
                plugins: {
                    zoom: {
                        pan: {
                            enabled: true,
                            mode: 'x',
                            modifierKey: null,
                        },
                        zoom: {
                            wheel: {
                                enabled: true,
                            },
                            pinch: {
                                enabled: true,
                            },
                            mode: 'x',
                        },
                    },
                },
                scales: {
                    x: {
                        display: true,
                        ticks: {
                            maxRotation: 90,
                            minRotation: 90,
                            maxTicksLimit: 20,
                        }
                    },
                    y: {
                        type: 'linear',
                        display: true,
                        position: 'left',
                        title: {
                            display: true,
                            text: 'Price / Moving Average'
                        }
                    },
                    y1: {
                        type: 'linear',
                        display: true,
                        position: 'right',
                        grid: {
                            drawOnChartArea: false,
                        },
                        title: {
                            display: true,
                            text: 'Derivatives'
                        }
                    },
                    y2: {
                        type: 'linear',
                        display: true,
                        position: 'right',
                        grid: {
                            drawOnChartArea: false,
                        },
                        title: {
                            display: true,
                            text: 'Total Asset Value (USDC)'
                        },
                        ticks: {
                            callback: function(value, index, ticks) {
                                return '$' + value.toFixed(2);
                            }
                        },
                        offset: true,
                    },
                    y3: {
                        type: 'linear',
                        display: true,
                        position: 'left',
                        grid: {
                            drawOnChartArea: false,
                        },
                        title: {
                            display: true,
                            text: 'Standard Deviation'
                        },
                        offset: true,
                    },
                }
            }
        });

        // Add double-click event listener to reset zoom
        const canvas = document.getElementById('chart');
        canvas.addEventListener('dblclick', function(){
            chart.resetZoom();
        });
    } else {
        // Update existing chart data
        chart.data.labels = labels;
        chart.data.datasets[0].data = priceData;
        chart.data.datasets[1].data = ma99Data;
        chart.data.datasets[2].data = ma7Data;
        chart.data.datasets[3].data = stdDev99Data;
        chart.data.datasets[4].data = derivativeData;
        chart.data.datasets[5].data = secondDerivativeData;
        chart.data.datasets[6].data = zeroData;
        chart.data.datasets[7].data = ma99DerivativeData;
        chart.data.datasets[8].data = derivativeOfMA99DerivativeData;
        chart.data.datasets[9].data = specialPointsData;
        chart.data.datasets[10].data = totalAssetValueData;
        chart.update();
    }
}
</script>
</body>
</html>" this is my strategy testing code. calculate moving average 39 of derivative of ma99 of derivative. draw it on graph too. give the full code.