geSigmoid
Download scriptOverview
The geSigmoid script is a specialized technical analysis tool designed for the MetaTrader platform. Its primary purpose is to visualize price trends by applying a mathematical "S-curve" (known as a Sigmoid function) to specific historical price points. Unlike standard moving averages that simply smooth out noise, this tool attempts to map the transition between two significant price extremes into a fluid, organic curve.
Core Logic and Mechanism
The script operates by identifying key boundaries in the market data and interpolating the space between them. Here is the step-by-step logic of how it processes information:
1. Dynamic Point Identification The script automatically looks for two distinct reference points on your chart. It identifies a "Left" point (historical) and a "Right" point (current/recent). It determines the distance between these two points in time to calculate the scale of the trend.
2. Extremity Analysis To determine the range of the curve, the script compares the closing prices of these two identified points:
- If the price at the left point is higher than the price at the right point, it uses the high of the left and the low of the right as its boundaries.
- If the price at the left point is lower, it reverses that logic. This ensures that the resulting curve always encompasses the relevant price action between the two points.
3. The Sigmoid Curve Calculation The "Sigmoid" part of the name refers to the mathematical formula used to draw the line. Instead of a straight diagonal line, the script calculates an "Alpha" value—a growth rate based on your settings—to create a smooth, flowing curve.
- It applies an exponential decay/growth logic so that the line starts flat near one price point, curves aggressively in the middle, and flattens out again as it approaches the other price point.
- This mimics a natural transition, helping traders visualize the "flow" of a trend rather than just the raw price movement.
4. Visual Rendering The script handles all the heavy lifting of drawing on the chart:
- It places visual markers (arrows) to indicate where it has anchored the start and end points of its calculation.
- It dynamically redraws the sigmoid line as new price data arrives, shifting the curve in real-time to maintain the relationship between the historical anchor and the current market price.
Summary for the User
Essentially, this tool takes two specific moments in time and draws a sophisticated, curved bridge between them. It is designed to provide a more "organic" view of price progression, highlighting the transition from one price level to another by smoothing out the path in a way that standard linear tools cannot.
//+------------------------------------------------------------------+
//| geSigmoid.mq4 |
//| Copyright © 2007, ver 1.0 |
//| Forte928 |
//+------------------------------------------------------------------+
#property copyright "Forte928"
#property link ""
#define IndicatorName "geSigmoid"
#property indicator_chart_window
//roperty indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Tomato
#property indicator_color2 YellowGreen
#property indicator_color3 Wheat
#property indicator_color4 LightSeaGreen
extern int FirstPoint = 50;
extern double Error = 0.005;
extern int WidthPoint = 3;
extern int WidthLine = 2;
//double FreqTOL =0.0001;//Tolerance of frequency calculation for Method 1
double FxView1[];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Work Variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
double TimeBuf1[];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Initialization program Buffers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void InitBufferam(int iBufferSize)
{
ArrayResize(TimeBuf1,iBufferSize);
return;
}
void EmptyBufferam()
{
ArrayInitialize(TimeBuf1,EMPTY_VALUE);
// -->
ArrayInitialize(FxView1,EMPTY_VALUE);
return;
}
void DoneBufferam()
{
ArrayResize(TimeBuf1,0);
return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Program Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int MaxPeriod=0;
int CalcCount=0;
string UniqueName="";
double FxLeft=0;
double FxRight=0;
int IxLeft=0;
int IxRight=0;
int IxCount=0;
int Counter=2000;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Custom indicator initialization function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int init()
{
//---- initialization program values --------------------------------
MaxPeriod=0;//MathMax(EMAPrd,WinSize);
InitBufferam(MaxCounter(Counter,MaxPeriod));
CalcCount=InitCounter(Counter,MaxPeriod);
//---- initialization indicators -------------------------------------
SetupChartLine(0,FxView1,0,WidthLine,"Sigmoid"+FirstPoint);// SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(0,ValueBuf0);
MathSrand(TimeLocal());
UniqueName=IndicatorName+MathRand();
IxLeft=FirstPoint;
//----
return(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Custom indicator deinitialization function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int deinit()
{
//----
DoneBufferam();
ObjectDelete(UniqueName+"LF");
ObjectDelete(UniqueName+"RG");
//----
return(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start defination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int start()
{
if (!StartCounter(IndicatorName,Counter,CalcCount,MaxPeriod)) return(-1);
//------------------------------------------------------------------------------------
EmptyBufferam();
//+-------------------------- Begin Cycle ---------------------------------------------------+\\
if (ObjectFind(UniqueName+"LF")<0) {
ObjectCreate(UniqueName+"LF",OBJ_ARROW,0,0,0);
ObjectSet(UniqueName+"LF",OBJPROP_TIME1,Time[IxLeft]);
ObjectSet(UniqueName+"LF",OBJPROP_PRICE1,Low[IxLeft]+10*Point);
ObjectSet(UniqueName+"LF",OBJPROP_ARROWCODE,5);
ObjectSet(UniqueName+"LF",OBJPROP_WIDTH,WidthPoint);
}
if (ObjectFind(UniqueName+"RG")<0) {
ObjectCreate(UniqueName+"RG",OBJ_ARROW,0,0,0);
ObjectSet(UniqueName+"RG",OBJPROP_TIME1,Time[0]);
ObjectSet(UniqueName+"RG",OBJPROP_PRICE1,High[0]+10*Point);
ObjectSet(UniqueName+"RG",OBJPROP_ARROWCODE,6);
ObjectSet(UniqueName+"RG",OBJPROP_WIDTH,WidthPoint);
}
IxLeft=iBarShift(NULL,Period(),ObjectGet(UniqueName+"LF",OBJPROP_TIME1),false);
IxRight=iBarShift(NULL,Period(),ObjectGet(UniqueName+"RG",OBJPROP_TIME1),false);
IxCount=IxLeft-IxRight+1;
SetIndexShift(0,IxCount);//(IxLeft-IxRight));
double Alpha=-MathLog(1/Error-1)/(-IxCount);
if (Close[IxLeft]>Close[IxRight]) {
FxLeft=High[IxLeft];
FxRight=Low[IxRight];
}
else {
FxLeft=Low[IxLeft];
FxRight=High[IxRight];
}
Print(FxLeft," ",FxRight);
for (int Rx=IxCount-1;Rx>=0;Rx--){
TimeBuf1[Rx+IxCount]=1/(1+MathExp(-Alpha*(-Rx)))*(FxRight-FxLeft)/0.5+FxLeft;
TimeBuf1[Rx]=1/(1+MathExp(-Alpha*(IxCount-Rx)))*(FxRight-FxLeft)/0.5+FxLeft;
}
ArrayCopy(FxView1,TimeBuf1,IxRight,0,IxCount*2);
// ArrayCopy(FxView2,TimeBuf4,Shift,0,CalcCount);
// ArrayCopy(FxView3,TimeBuf5,Shift,0,CalcCount);
// ArrayCopy(FxView4,TimeBuf6,Shift,0,CalcCount);
//----
return(0);
}
//-----------------------------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ InitCounter ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int InitCounter(int iPreCount,int iMaxPeriod)
{
// Rule 1
//if ((Result==0)||(Result>Bars)) Result=Bars;
int Result=MaxCounter(iPreCount,iMaxPeriod);
// Rule 2
if ((Result+iMaxPeriod)>Bars) Result=Bars-iMaxPeriod;
// Rule 3
if (Result<iMaxPeriod) Result=0;
else Result=Result+iMaxPeriod;
return(Result);
}
//------------------------------------------ StartCounter --------------------------
bool StartCounter(string WindowName,int iPreCount,int& iCalcCount,int iMaxPeriod)
{
if ((iPreCount>iCalcCount)||(iPreCount==0)) iCalcCount=InitCounter(iPreCount,iMaxPeriod);
if (iCalcCount==0)
{
Alert(WindowName+" "+Symbol()+"("+Period()+") - Limited Calculate Period");
return(false);
}
return(true);
//int iBarCount=IndicatorCounted();
//if (iBarCount>0) return(true);
//Print("StartCounter");
return(false);
}
//------------------------------------------ StartCounter --------------------------
int MaxCounter(int iPreCount,int iMaxPeriod)
{
int Result=iPreCount;
// Rule 1
//if ((Result==0)||(Result>Bars)) Result=Bars;
if (Result==0) Result=Bars-1;
if (Result<iMaxPeriod) Result=iMaxPeriod;
return(Result+iMaxPeriod);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Style active Line ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SetupChartLine(int Index,double& ViewAy[],int Style,int Width,string Label)
{
switch(Style)
{
case 0 : SetIndexStyle(Index,DRAW_LINE,STYLE_SOLID,Width);break;
case 1 : SetIndexStyle(Index,DRAW_HISTOGRAM,STYLE_SOLID,Width);break;
case 2 : SetIndexStyle(Index,DRAW_ARROW,STYLE_SOLID,Width);break;
default : SetIndexStyle(Index,DRAW_LINE,STYLE_SOLID,Width);break;
}
if (Label!="") SetIndexLabel(Index,Label);
SetIndexBuffer(Index,ViewAy);
return(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comments