-
Notifications
You must be signed in to change notification settings - Fork 47
Open
Description
Hello, everyone.
I am definitely not a coder. I have several indicators that are causing problems on OnPaintChart, from the QuantowerAlgo API.
Here is one of my codes that is supposed to display the volume profile.
Can anyone help me identify the errors? I would be very grateful. I would really like to learn how to code, as I am very curious but know nothing about the world of coding.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace CustomIndicators
{
public class VolumeProfileIndicator : Indicator, IVolumeAnalysisIndicator
{
[InputParameter("Position X", 0, 0, 1000, 10, 0)]
public int PositionX = 20;
[InputParameter("Position Y", 1, 0, 1000, 10, 0)]
public int PositionY = 30;
[InputParameter("Espacement lignes", 2, 1, 50, 1, 0)]
public int LineSpacing = 20;
private Dictionary<double, double> volumeByPrice = new Dictionary<double, double>();
public VolumeProfileIndicator()
{
this.Name = "Volume Profile Display";
this.Description = "Affiche le volume total à chaque niveau de prix";
this.SeparateWindow = false;
}
protected override void OnInit()
{
// Initialisation
}
protected override void OnUpdate(UpdateArgs args)
{
// Vérifier si les données de volume sont disponibles
if (this.HistoricalData.VolumeAnalysisCalculationProgress == null ||
this.HistoricalData.VolumeAnalysisCalculationProgress.State != VolumeAnalysisCalculationState.Finished)
return;
// Réinitialiser les données
volumeByPrice.Clear();
// Récupérer les données de volume pour la barre actuelle
var currentItem = this.HistoricalData[0];
if (currentItem.VolumeAnalysisData == null || currentItem.VolumeAnalysisData.PriceLevels == null)
return;
// Parcourir tous les niveaux de prix et accumuler le volume
foreach (var priceLevel in currentItem.VolumeAnalysisData.PriceLevels)
{
double price = priceLevel.Key; // La clé du dictionnaire est le prix
var volumeData = priceLevel.Value; // La valeur contient les données de volume
double totalVolume = volumeData.AskVolume + volumeData.BidVolume;
if (!volumeByPrice.ContainsKey(price))
{
volumeByPrice[price] = 0;
}
volumeByPrice[price] += totalVolume;
}
}
// Implémentation de IVolumeAnalysisIndicator
public bool IsRequirePriceLevelsCalculation => true;
public void VolumeAnalysisData_Loaded()
{
this.Refresh();
}
public override void OnPaintChart(PaintChartEventArgs args)
{
base.OnPaintChart(args);
if (volumeByPrice.Count == 0) return;
Graphics gr = args.Graphics;
// Créer une police
Font font = new Font("Arial", 9);
Font fontBold = new Font("Arial", 9, FontStyle.Bold);
// Trier les prix par ordre décroissant pour affichage
var sortedVolumes = volumeByPrice.OrderByDescending(kvp => kvp.Key).ToList();
// Afficher les en-têtes
gr.DrawString("Prix", fontBold, Brushes.Yellow, PositionX, PositionY - 20);
gr.DrawString("Volume", fontBold, Brushes.Yellow, PositionX + 80, PositionY - 20);
gr.DrawString("Ask", fontBold, Brushes.LightGreen, PositionX + 160, PositionY - 20);
gr.DrawString("Bid", fontBold, Brushes.LightCoral, PositionX + 220, PositionY - 20);
// Afficher chaque niveau de prix avec son volume
int displayCount = Math.Min(sortedVolumes.Count, 30); // Limiter à 30 niveaux max
for (int i = 0; i < displayCount; i++)
{
var priceVolumeEntry = sortedVolumes[i];
double price = priceVolumeEntry.Key;
double totalVolume = priceVolumeEntry.Value;
int yPosition = PositionY + (LineSpacing * i);
// Récupérer les détails Ask/Bid pour ce niveau de prix
var currentItem = this.HistoricalData[0];
double askVolume = 0;
double bidVolume = 0;
if (currentItem.VolumeAnalysisData != null &&
currentItem.VolumeAnalysisData.PriceLevels != null &&
currentItem.VolumeAnalysisData.PriceLevels.ContainsKey(price))
{
var volumeData = currentItem.VolumeAnalysisData.PriceLevels[price];
askVolume = volumeData.AskVolume;
bidVolume = volumeData.BidVolume;
}
// Afficher le prix
gr.DrawString(price.ToString("F2"), font, Brushes.LightGray, PositionX, yPosition);
// Afficher le volume total
gr.DrawString(totalVolume.ToString("F0"), font, Brushes.White, PositionX + 80, yPosition);
// Afficher le volume Ask (vert)
gr.DrawString(askVolume.ToString("F0"), font, Brushes.LightGreen, PositionX + 160, yPosition);
// Afficher le volume Bid (rouge)
gr.DrawString(bidVolume.ToString("F0"), font, Brushes.LightCoral, PositionX + 220, yPosition);
}
// Trouver et afficher le POC (Point of Control - prix avec le plus de volume)
if (sortedVolumes.Count > 0)
{
var pocEntry = volumeByPrice.OrderByDescending(kvp => kvp.Value).First();
int pocIndex = sortedVolumes.FindIndex(kvp => kvp.Key == pocEntry.Key);
if (pocIndex >= 0 && pocIndex < displayCount)
{
int pocY = PositionY + (LineSpacing * pocIndex);
// Surligner le POC avec un rectangle
using (var pen = new Pen(Color.Yellow, 2))
{
gr.DrawRectangle(pen, PositionX - 5, pocY - 2, 280, LineSpacing - 2);
}
}
}
font.Dispose();
fontBold.Dispose();
}
}
}
Metadata
Metadata
Assignees
Labels
No labels