Skip to content

Instantly share code, notes, and snippets.

@fatfingererr
Created June 20, 2022 10:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fatfingererr/c1a2a59dd5ab2877824bb89894f89e60 to your computer and use it in GitHub Desktop.
Save fatfingererr/c1a2a59dd5ab2877824bb89894f89e60 to your computer and use it in GitHub Desktop.
VolumeProfileCalculate
// 完整来源 (Metatrader, MQL, 类似 C++):
// https://www.earnforex.com/metatrader-indicators/volume-profile/
void VolumeProfileCalculate(){
// 根据参数设置找到起始bar数
int BarStart=iBarShift(Symbol(),VPTimeFrame,StartTime);
// 如果要整跟 KLINE 都做统计 (=Whole), 还是一根 KLINE 只统计 Close 或 Open
int PriceHighMode=MODE_CLOSE;
int PriceLowMode=MODE_CLOSE;
if(CalculationMode==CANDLE_WHOLE){
PriceHighMode=MODE_HIGH;
PriceLowMode=MODE_LOW;
}
if(CalculationMode==CANDLE_CLOSE){
PriceHighMode=MODE_CLOSE;
PriceLowMode=MODE_CLOSE;
}
if(CalculationMode==CANDLE_OPEN){
PriceHighMode=MODE_OPEN;
PriceLowMode=MODE_OPEN;
}
// 找到当前时间范围内最低与最高价
PriceMin=MathFloor(iLow(Symbol(),VPTimeFrame,iLowest(Symbol(),VPTimeFrame,(ENUM_SERIESMODE)PriceLowMode,BarsToScan,BarStart))/StepPoints)*StepPoints;
PriceMax=MathCeil(iHigh(Symbol(),VPTimeFrame,iHighest(Symbol(),VPTimeFrame,(ENUM_SERIESMODE)PriceHighMode,BarsToScan,BarStart))/StepPoints)*StepPoints;
// 计算 step 宽度, 也就是累计的 step, 太细也不会有太大差别
Steps=(int)MathCeil((PriceMax-PriceMin)/StepPoints)+1;
ArrayResize(VolumeProfile,Steps);
ArrayInitialize(VolumeProfile,0);
// 从起始开始统计
for(int i=0; i<BarsToScan; i++){
int j=BarStart+i;
double MinPrice=0;
double MaxPrice=0;
double CandleSteps=0;
// 根据模式不同, 统计的基础不同
if(CalculationMode==CANDLE_WHOLE){
MinPrice=iLow(Symbol(),VPTimeFrame,j);
MaxPrice=iHigh(Symbol(),VPTimeFrame,j);
}
if(CalculationMode==CANDLE_CLOSE){
MinPrice=iClose(Symbol(),VPTimeFrame,j);
MaxPrice=iClose(Symbol(),VPTimeFrame,j);
}
if(CalculationMode==CANDLE_OPEN){
MinPrice=iOpen(Symbol(),VPTimeFrame,j);
MaxPrice=iOpen(Symbol(),VPTimeFrame,j);
}
MinPrice=MathFloor(MinPrice/StepPoints)*StepPoints;
MaxPrice=MathFloor(MaxPrice/StepPoints)*StepPoints;
CandleSteps=MathRound((MaxPrice-MinPrice)/StepPoints);
// 针对一根 KLINE 从底向上开始统计
for(int k=0; k<=CandleSteps; k++){
double CalcPrice=MinPrice+StepPoints*k;
int h=(int)MathRound((CalcPrice-PriceMin)/StepPoints);
long Weight=1;
if(UseVolume) Weight=iVolume(Symbol(),VPTimeFrame,j);
if(h>=Steps){
MessageBox("Historical Data not loaded, please reload the indicator","WARNING",MB_OK);
Print("Error with historical data, please reload the indicator");
continue;
}
// 在 profile 区间内疚做累计
VolumeProfile[h]+=Weight;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment