Author: Forte928
geSigmoid

Overview

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.

Miscellaneous
It issuies visual alerts to the screenImplements a curve of type %1
13 Views
0 Downloads
0 Favorites
geSigmoid
//+------------------------------------------------------------------+
//|																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