#property description "지표는 지난 달의 데이터를 분석하고 크기가 작은 모든 캔들스틱을 그립니다"
#property description "그리고 큰 틱 볼륨. 틱 볼륨 배열이 정렬됩니다"
#property description "그러한 캔들스틱을 정의하기 위해. 첫 번째 InpSmallVolume으로 구성된 볼륨이 있는 캔들스틱"
#property description "배열의 백분율이 작은 것으로 간주됩니다. 틱 볼륨이 있는 캔들스틱이 구성됩니다 "
#property description "배열의 마지막 InpBigVolume 백분율이 큰 것으로 간주됩니다."
//--- 지표 설정
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots 1
//--- 플롯
#property indicator_label1 "VolumeFactor"
#property indicator_type1 DRAW_COLOR_CANDLES
#property indicator_color1 clrDodgerBlue,clrOrange
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- 사전정의된 상수
#define INDICATOR_EMPTY_VALUE 0.0
//--- 매개변수 입력
input int InpSmallVolume=15; // 작은 볼륨의 백분율 값 (<50)
input int InpBigVolume=20; // 큰 볼륨의 백분율 값 (<50)
//--- 분석 시작 시간(이동 예정)
datetime ExtStartTime;
//--- 지표 버퍼
double ExtOpenBuff[];
double ExtHighBuff[];
double ExtLowBuff[];
double ExtCloseBuff[];
double ExtColorBuff[];
//--- 캔들스틱 표시를 위한 볼륨 경계 값
long ExtLeftBorder=0;
long ExtRightBorder=0;
//+------------------------------------------------------------------+
//| 틱 볼륨에 대한 테두리 값 수신 |
//+------------------------------------------------------------------+
bool GetVolumeBorders(void)
{
//--- 변수
datetime stop_time; // 종료 시간 복사
long buff[]; // 복사할 버퍼
//--- 종료 시간이 현재 시간입니다
stop_time=TimeCurrent();
//--- 시작 시간이 현재 시간보다 힌 달 빠릅니다
ExtStartTime=GetStartTime(stop_time);
//--- 틱 볼륨 값 수신
ResetLastError();
if(CopyTickVolume(Symbol(),Period(),ExtStartTime,stop_time,buff)==-1)
{
//--- 데이터 수신 실패, 재연산 명령을 시작하기 위해 false를 반환
PrintFormat("틱 볼륨 값을 수신하는데 실패. 오류 코드 = %d",GetLastError());
return(false);
}
//--- 배열 크기 계산
int size=ArraySize(buff);
//--- 배열을 정리
ArraySort(buff);
//--- 틱 볼륨 좌측 및 우측 테두리 값 정의
ExtLeftBorder=buff[size*InpSmallVolume/100];
ExtRightBorder=buff[(size-1)*(100-InpBigVolume)/100];
//--- 실행 성공
return(true);
}
//+------------------------------------------------------------------+
//| 전달된 데이터보다 한 달 적은 데이터 수신 |
//+------------------------------------------------------------------+
datetime GetStartTime(const datetime stop_time)
{
//--- 종료시간을 MqlDateTime 유형 구조 변수로 변환
MqlDateTime temp;
TimeToStruct(stop_time,temp);
//--- 한 달 적은 데이터를 수신
if(temp.mon>1)
temp.mon-=1; // 현재 달이 연도의 첫 번째 달이 아니므로 이전 달의 수가 하나 줄어듭니다
else
{
temp.mon=12; // 현재 달은 연도의 첫 번째 달이므로 이전 달의 수는 12,
temp.year-=1; // 연수가 하나 줄면
}
//--- 일수는 28을 초과하지 않습니다
if(temp.day>28)
temp.day=28;
//--- 기일을 반환
return(StructToTime(temp));
}
//+------------------------------------------------------------------+
//| 사용자 지정 지표 초기화 함수 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 입력 매개변수가 조건을 충족하는지 확인
if(InpSmallVolume<0 || InpSmallVolume>=50 || InpBigVolume<0 || InpBigVolume>=50)
{
Print("잘못된 입력 매개변수");
return(INIT_PARAMETERS_INCORRECT);
}
//--- 지표 버퍼 맵핑
SetIndexBuffer(0,ExtOpenBuff);
SetIndexBuffer(1,ExtHighBuff);
SetIndexBuffer(2,ExtLowBuff);
SetIndexBuffer(3,ExtCloseBuff);
SetIndexBuffer(4,ExtColorBuff,INDICATOR_COLOR_INDEX);
//--- 표시하지 않을 값을 설정
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);
//--- 지표 버퍼에 대한 라벨 설정
PlotIndexSetString(0,PLOT_LABEL,"시가;고가;저가;종가");
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 사용자 지정 지표 반복 함수 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//--- 아직 처리되지 않은 바가 있는지 확인
if(prev_calculated<rates_total)
{
//--- 볼륨에 대한 우측 및 좌측 테두리의 새 값을 수신
if(!GetVolumeBorders())
return(0);
}
//--- 막대 계산을 위한 시작 변수
int start=prev_calculated;
//--- 지표 값이 이전 틱에서 이미 계산된 경우 마지막 막대에서 작업
if(start>0)
start--;
//--- 시계열에서 직접 인덱싱 설정
ArraySetAsSeries(time,false);
ArraySetAsSeries(open,false);
ArraySetAsSeries(high,false);
ArraySetAsSeries(low,false);
ArraySetAsSeries(close,false);
ArraySetAsSeries(tick_volume,false);
//--- 지표 값의 계산 루프
for(int i=start;i<rates_total;i++)
{
//--- 초기 데이터 시작부터 캔들스틱을 채움
if(ExtStartTime<=time[i])
{
//--- 값이 우측 테두리보다 작지 않으면 캔들스틱을 채움
if(tick_volume[i]>=ExtRightBorder)
{
//--- 캔들스틱을 그리기 위한 데이터 수신
ExtOpenBuff[i]=open[i];
ExtHighBuff[i]=high[i];
ExtLowBuff[i]=low[i];
ExtCloseBuff[i]=close[i];
//--- DodgerBlue 색상
ExtColorBuff[i]=0;
//--- 루프를 계속
continue;
}
//--- 값이 좌측 테두리를 초과하지 않으면 캔들스틱을 채움
if(tick_volume[i]<=ExtLeftBorder)
{
//--- 캔들스틱을 그리기 위한 데이터 수신
ExtOpenBuff[i]=open[i];
ExtHighBuff[i]=high[i];
ExtLowBuff[i]=low[i];
ExtCloseBuff[i]=close[i];
//--- 주황색 색상
ExtColorBuff[i]=1;
//--- 루프를 계속
continue;
}
}
//--- 계산에 포함되지 않은 막대의 빈 값을 설정
ExtOpenBuff[i]=INDICATOR_EMPTY_VALUE;
ExtHighBuff[i]=INDICATOR_EMPTY_VALUE;
ExtLowBuff[i]=INDICATOR_EMPTY_VALUE;
ExtCloseBuff[i]=INDICATOR_EMPTY_VALUE;
}
//--- 다음 호출을 위한 prev_calculated의 반환 값
return(rates_total);
}
|