Batfink Signal (Target 1)
Download scriptThe Batfink Daily Range indicator is designed to identify specific price breakout levels based on time-segmented market activity. Instead of looking at the entire trading day as a single block, this script analyzes distinct time windows to establish "zones" and alert you when the price moves beyond them.
Core Logic and Functionality
Time Zone Synchronization The script is built to handle different global markets by allowing you to input your local time zone and the destination time zone. It calculates the offset between these two, ensuring that the time windows (like "morning" or "afternoon" sessions) are accurately mapped regardless of which country your broker is based in.
Dynamic Session Monitoring The logic segments each trading day into three specific chronological periods. The script monitors these periods to track high and low price points.
- It identifies the price action during the initial time blocks.
- Once a session is completed, it "carries forward" the data from that period to create a reference range for the rest of the day.
Zone Projection Based on the data gathered from the first completed session, the script calculates an upper and lower "Entry Zone."
- The indicator projects these levels onto your chart as horizontal lines.
- It applies a customizable "Pips For Entry" buffer to these levels. This means the boundary isn't just the raw price of the previous session; it is adjusted by a specific amount of pips to provide a bit of "breathing room" before a signal is confirmed.
Breakout Detection The script continuously watches the current market price against these projected upper and lower boundaries. It looks for specific "breakout" behaviors:
- Buy Signals: Triggered when the price moves above the upper boundary. The logic checks if the candle's high exceeds the zone while the opening price remains below it, or if the previous candle closed below but the current one opened above.
- Sell Signals: Triggered when the price drops below the lower boundary. It looks for a similar cross where the candle's low dips below the zone while the opening price remains above it.
Visual and Audible Alerts When these conditions are met, the script performs two actions:
- Visual Marking: It places an arrow on the chart at the exact point where the breakout occurred.
- Notifications: If enabled in the settings, it triggers a real-time "Zone Breakout" alert on your trading platform to notify you immediately of the price movement.
Summary for the User
Essentially, this tool automates the process of watching specific time windows to see how the market behaved early in the day. It then draws "lines in the sand" based on that behavior. When the market finally breaks through those lines later in the day, the script highlights it for you, helping you identify potential momentum shifts or trend continuations.
//+------------------------------------------------------------------+
//| Batfink Daily Range.MT4 |
//| |
//+------------------------------------------------------------------+
/* Introduction:
Draw Line at 00:00GMT + and - 55
TimeZONE Information - Indicator can be used for different Time Zones.
For Batfink settings set to -5 for MetaQuotes demo Server
This will place home line at 00:00GMT Time
*/
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 Red
#property indicator_color3 Orange
extern bool DoEntryAlerts= false;
extern int LocalTimeZone= 2;
extern int DestTimeZone= 0;
extern int PipsForEntry= 55;
double Zone1Upper[];
double Zone1Lower[];
double EntrySignalsBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,Zone1Upper);
SetIndexEmptyValue(0, 0.0);
SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,Zone1Lower);
SetIndexEmptyValue(1, 0.0);
SetIndexStyle(2,DRAW_ARROW);
SetIndexArrow(2, 140);
SetIndexBuffer(2, EntrySignalsBuffer);
SetIndexEmptyValue(2, 0.0);
SetIndexLabel(2, "Zone Breakout Signal");
return(0);
}
int deinit()
{
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars= IndicatorCounted(),
lastbar, result;
if (Bars<=100)
return(0);
if (counted_bars>0)
counted_bars--;
lastbar= Bars - counted_bars;
BreakoutRanges(0, lastbar, LocalTimeZone, DestTimeZone);
//
// check alerts
//
static datetime lastalerttime;
static double lastalertprice;
if (DoEntryAlerts && lastalerttime!=Time[0] && EntrySignalsBuffer[0]!=0 && EntrySignalsBuffer[0]!=lastalertprice) {
Alert("ZoneBreakout signals entry!");
lastalerttime= Time[0];
lastalertprice= EntrySignalsBuffer[0];
}
else {
lastalerttime= 0;
lastalertprice= 0.0;
}
return(0);
}
//+------------------------------------------------------------------+
//| Compute index of first/last bar of yesterday and today |
//+------------------------------------------------------------------+
int BreakoutRanges(int offset, int lastbar, int tzlocal, int tzdest)
{
int i, j, k,
tzdiff= tzlocal - tzdest,
tzdiffsec= tzdiff*3600,
tidxstart[2]= { 0, 0},
tidxend[2]= { 0, 0 };
double topen[2]= { 0.0, 0.0 },
tclose[2]= { 99999.9, 99999.9 };
string tfrom[3]= { "07:00", "08:00" , /*rest of day: */ "12:00"},
tto[3]= { "08:00", "12:00", /*rest of day: */ "24:00" },
tday;
bool inperiod= -1;
datetime timet;
//
// search back for the beginning of the day
//
tday= TimeToStr(Time[lastbar]-tzdiffsec, TIME_DATE);
for ( ; lastbar<Bars; lastbar++) {
if (TimeToStr(Time[lastbar] - tzdiffsec, TIME_DATE)!=tday) {
lastbar--;
break;
}
}
//
// find the high/low for the two periods and carry them forward through the day
//
tday= "XXX";
for (i= lastbar; i>=offset; i--) {
timet= Time[i] - tzdiffsec; // time of this bar
string timestr= TimeToStr(timet, TIME_MINUTES), // current time HH:MM
thisday= TimeToStr(timet, TIME_DATE); // current date
EntrySignalsBuffer[i]= 0;
//
// for all three periods (first period, second period, rest of day)
//
for (j= 0; j<3; j++) {
if (tfrom[j]<=timestr && timestr<tto[j]) { // Bar[i] in this period
if (inperiod!=j) { // entered new period, so last one is completed
if (j>0) { // now draw high/low back over the recently completed period
for (k= tidxstart[j-1]; k>=tidxend[j-1]; k--) {
if (j-1==0) {
Zone1Upper[k]= tclose[j-1];
Zone1Lower[k]= tclose[j-1];
}
}
inperiod= j; // remember current period
}
// for the current period find idxstart, idxend and compute high/low
if (tidxstart[j]==0) {
tidxstart[j]= i;
tday= thisday;
}
tidxend[j]= i;
topen[j]= MathMax(topen[j], Open[i]);
tclose[j]= MathMin(tclose[j], Close[i]);
}
}
//------------------------------------------------------------------------
// carry forward the periods for which we have definite high/lows
//
if (inperiod>=1 && tday==thisday) { // first time period completed
Zone1Upper[i]= tclose[0] + PipsForEntry*Point;
Zone1Lower[i]= tclose[0] - PipsForEntry*Point;
}
CheckSignal(i, Zone1Upper[i], OP_BUY, EntrySignalsBuffer);
CheckSignal(i, Zone1Lower[i], OP_SELL, EntrySignalsBuffer);
}
{ // none yet to carry forward (zero to clear old values, e.g. from switching timeframe)
Zone1Upper[i]= 0;
Zone1Lower[i]= 0;
}
//
// at the beginning of a new day reset everything
//
if (tday!="XXX" && tday!=thisday) {
Print("#", i, "new day ", thisday, "/", tday);
tday= "XXX";
inperiod= -1;
for (j= 0; j<2; j++) {
tidxstart[j]= 0;
tidxend[j]= 0;
topen[j]= 0;
tclose[j]= 99999;
}
}
}
return (0);
}
//+------------------------------------------------------------------+
//| Check price break |
//+------------------------------------------------------------------+
bool CheckSignal(int shift, double price, int type, double &signalbuffer[])
{
bool signal= false;
if (type==OP_BUY && ((Open[shift]<price && High[shift]>price) || (Close[shift+1]<price && Open[shift]>price)) ) {
signalbuffer[shift]= price;
signal= true;
}
if (type==OP_SELL && (Open[shift]>price && Low[shift]<price) || (Close[shift+1]>price && Open[shift]<price)) {
signalbuffer[shift]= price;
signal= true;
}
return (signal);
}
Comments