Convert following Amibroker code for Volume Spread Analysis Indicator (VSA) into Metatrader (MT4) indicator, with the source code. You must agree not to resell if hired for this project.
## Deliverables
SECTION_BEGIN("Volume Analysis");
////////////////////////////////////////////////////////////////////////////////////
//
// Volume Analysis Studies
//
// this code studies price/volume based on information from
//
// * Master the Markets,
// * [login to view URL]
// * [login to view URL]
//
// I do not claim responsibility or liability for how this code is used.
// If you change the code in any way, please send me an updated copy of
// the changes to:
//
// tcoates_au@[login to view URL]
//
////////////////////////////////////////////////////////////////////////////////////
SetChartOptions(0,chartShowArrows|chartShowDates);
////////////////////////////////////////////////////////////////////////////////////
//
// constants
//
////////////////////////////////////////////////////////////////////////////////////
numDays = 30;
dwWideSpread = 1.8;
dwNarrowSpread = 0.8;
dwSpreadMiddle = 0.5;
dwHighClose = 0.7;
dwLowClose = 0.3;
volNumDays = 30; //numDays;
dwUltraHighVol = 2;
dwVeryHighVol = 2.2; // was 1.8
dwHighVol = 1.8; // was 1.8
dwAboveAvgVol = 1.5; // was 1.8
dwLowVol = 0.8; // was 0.8
//avgVolume = EMA(V, volNumDays);
volSpeedUp = 1; //int(numDays * 0.33);
avgVolume = EMA(EMA(V, volNumDays),volSpeedUp) ;
////////////////////////////////////////////////////////////////////////////////////
longTermAvg = int(EMA(C, 200) * 100);
medTermAvg = int(EMA(C, 50) * 100);
shortTermAvg = int(EMA(C, 10) * 100);
MAvgDir = EMA(C, 13);
MAvgDirTestDays = 30;
MAvgDirHigh = HHV(MAvgDir, MAvgDirTestDays);
MAvgDirLow = LLV(MAvgDir, MAvgDirTestDays);
MAvgDirTrend = IIf(MAvgDir > Ref(MAvgDirHigh, -1), 1,
IIf(MAvgDir < Ref(MAvgDirLow,-1), -1, 0));
////////////////////////////////////////////////////////////////////////////////////
//
// Classify each bar...
//
////////////////////////////////////////////////////////////////////////////////////
upBar = C > Ref(C,-1);
downBar = C < Ref(C,-1);
closeEqual = int(C*100) == int(Ref(C,-1)*100);
spread = H-L;
avgRange = Sum(spread, numDays) / numDays;
wideRange = spread >= (dwWideSpread * avgRange);
narrowRange = spread <= (dwNarrowSpread * avgRange);
testHighClose = L + (spread * dwHighClose);
testLowClose = L + (spread * dwLowClose);
testCloseMiddle = L + (spread * dwSpreadMiddle);
upClose = C > testHighClose;
upClose12 = C >= testCloseMiddle;
downClose = C < testLowClose;
downClose12 = C < testCloseMiddle;
middleClose = C >= testLowClose AND C <= testHighClose;
aboveAvgVolume = V > (avgVolume * dwAboveAvgVol);
highVolume = V > (avgVolume * dwHighVol);
veryHighVolume = V > (avgVolume * dwVeryHighVol);
ultraHighVolume = V > (avgVolume * dwUltraHighVol);
LowVolume = V < (avgVolume * dwLowVol);
markUpVol = (V > (avgVolume * dwLowVol)) AND (V <= (avgVolume * dwUltraHighVol));
markUpVol2 = markUpVol AND Ref(markUpVol,-1);
narrowBar1 = spread < Ref(spread,-1);
HH = H > Ref(H,-1);
LL = L < Ref(L,-1);
LH = H < Ref(H,-1);
////////////////////////////////////////////////////////////////////////////////////
//
// direction and title
//
////////////////////////////////////////////////////////////////////////////////////
ColorScheme = Param( "Color Scheme", 1, 0, 2, 1);
Trend_U = ( LLV( L, 20 ) + 2 * ATR( 10 ) );
Trend_D = ( HHV( H, 20 ) - 2 * ATR( 10 ) );
TrendUp = C >= Trend_U;
TrendDown = C < Trend_D;
////////////////////////////////////////////////////////////////////////////////////
//
// Basic patterns...
//
//
//see also:
//
// [login to view URL]
// [login to view URL]
//
// older definitions...
//
// upThrustBar = downClose AND HH AND (NOT narrowRange); // AND (H > Ref(HHV(H,4),-1)) ; //(C == L) AND;
////////////////////////////////////////////////////////////////////////////////////
testVolLow2 = (V < Ref(V,-1)) AND (V < Ref(V,-2));
testVolHigh2 = (V > Ref(V,-1)) AND (V > Ref(V,-2));
WRD = (spread > Ref(spread,-1)) AND (spread > Ref(spread,-2)) AND (spread > Ref(spread,-3));
////////////////////////////////////////////////////////////////////////////////////
// NO DEMAND
basicNoDemandBar = narrowRange AND Lowvolume AND upBar AND (upClose OR middleClose);
noDemandBar = basicNoDemandBar; // AND TrendUp;
////////////////////////////////////////////////////////////////////////////////////
// NO SUPPLY
basicNoSupplyBar = narrowRange AND LowVolume AND downBar AND (downclose OR middleClose);
// It is also common to find these bars in an up trend which are indications
// of continuation of the trend. They would also be found on consolidation bases.
// During up moves a No supply could indicate non participation from SM.
noSupplyBarUp = basicNoSupplyBar AND TrendUp;
// The No Supply bar is a narrow range Low Volume down bar closing in the lower half.
// The No Supply bars are found in the early Bottom reversals AND indicate strength.
noSupplyBarDown = basicNoSupplyBar AND TrendDown;
////////////////////////////////////////////////////////////////////////////////////
//
// STOPPING VOLUME
stoppingVolume1 = downBar AND upClose12 AND Highvolume;
stoppingVolume2 = Ref(wideRange,-1) AND Ref(HighVolume,-1) AND Ref(downClose12,-1)
AND upBar AND HH; // AND HighVolume;// AND upClose12;
stoppingVolume3 = Ref(wideRange,-1) AND Ref(HighVolume,-1) AND Ref(downClose12,-1)
AND upBar AND HighVolume AND upClose12;
stoppingVolume = TrendDown AND (stoppingVolume1 OR StoppingVolume2 OR StoppingVolume3);
////////////////////////////////////////////////////////////////////////////////////
//
// TEST
testBar = narrowRange AND lowvolume AND (C > testCloseMiddle);
testBar = testBar AND (NOT NoDemandBar);
////////////////////////////////////////////////////////////////////////////////////
//
// upThrustBar - see
// [login to view URL]
//
upThrustBar = WRD AND testVolHigh2 AND TrendUp AND HH AND downClose12 AND NOT Ref(upBar,1);
upThrustBarWithNoDemand = upThrustBar AND LowVolume;
upThrustBarWithSupplyOverDemand = upThrustBar AND testVolHigh2;
absorption = Ref(downbar, -1) AND Ref(highVolume, -1) AND upBar;
support = Ref(downBar,-1) AND (NOT Ref(downClose,-1)) AND Ref(highVolume,-1) AND upBar;
absorptionVolume1 = downBar AND downClose AND Highvolume AND Ref(upBar,1);
absorptionVolume2 = downBar AND downClose12 AND Highvolume AND Ref(upBar,1);
reverseUpThrust = TrendDown AND wideRange AND upClose AND Highvolume;
////////////////////////////////////////////////////////////////////////////////////
//
// Strength and Weakness
//
////////////////////////////////////////////////////////////////////////////////////
weakness1 = downBar AND downClose AND C < Ref(L,-1);
weakness = upThrustBar OR noDemandBar;
weaknessInUpTrend = weakness AND TrendUp;
weaknessInDownTrend = weakness AND TrendDown;
WideRangeAlert1 = wideRange AND aboveAvgVolume AND TrendUp AND (C < O);
WideRangeAlert2 = wideRange AND downClose12 AND TrendUp;
EffortToGoDown = wideRange AND aboveAvgVolume AND TrendUp AND downClose;
MyMarkUp = markUpVol AND Ref(markUpVol,-1) AND (MAvgDirTrend > 0) AND V > Ref(V,-1);
////////////////////////////////////////////////////////////////////////////////////
//
// Display stuff goes here!
//
////////////////////////////////////////////////////////////////////////////////////
OffSet = 0;
PlotShapes( shapeDownArrow*EffortToGoDown , colorIndigo , 0, H);
Offset += IIf(EffortToGoDown, 25, 5); //Offset = abs(Offset);
PlotShapes( shapeSmallSquare*(upThrustBarWithNoDemand OR upThrustBarWithSupplyOverDemand),
IIf(upThrustBarWithSupplyOverDemand, colorRed, colorDarkRed), 0, H, Offset);
Offset += IIf(upThrustBarWithNoDemand OR upThrustBarWithSupplyOverDemand, 25, 5); //Offset = abs(Offset);
//PlotShapes( shapeHollowDownArrow*weaknessInDownTrend, colorBrown, 0, H, Offset);
//Offset -= IIf(weaknessInDownTrend, 15, 0);
PlotShapes( shapeSmallCircle*NoDemandBar, colorBlack,0, H, Offset);
Offset += IIf(NoDemandBar, 15, 0);
PlotShapes( shapeSmallUpTriangle*stoppingVolume, IIf(stoppingVolume, colorGreen, colorSeaGreen),0, L);
PlotShapes( shapeSmallCircle*testBar , colorBlue,0, L);
PlotShapes( shapeSmallUpTriangle*reverseUpThrust , colorDarkGreen, 0, L);
PlotShapes( shapeSmallCircle*(noSupplyBarUp OR noSupplyBarDown), colorPink,0, L);
//PlotShapes( shapeSmallUpTriangle*MyMarkUp , colorSeaGreen, 0, L);
//Plot( testCloseMiddle, "", colorBlack, styleDots );
//PlotShapes( shapeSmallCircle*markUpVol2, colorBrown,0, L, negY);
//Plot( TREND_U, "", colorRed);
Color0 = colorBlack;
Color1 = IIf(wideRange, colorBlue,
IIf( narrowRange, colorLightBlue,
IIf( upBar, colorDarkGreen,
IIf( downBar, colorRed, colorDarkGrey))));
Color2 = IIf( TrendUp, colorDarkGreen,
IIf( TrendDown, colorRed, colorBlack));
Color = IIf(ColorScheme == 0, Color0,
IIf(ColorScheme == 1, Color1, Color2));
Plot( C, "Close", Color, styleNoTitle | ParamStyle("Style") | GetPriceStyle() );
////////////////////////////////////////////////////////////////////////////////////
//
// trend direction...
//
////////////////////////////////////////////////////////////////////////////////////
Dir = EncodeColor(colorBlack) + "Volume: " +
WriteIf(ultraHighVolume , "Ultra High",
WriteIf(veryHighVolume , "Very High",
WriteIf(highVolume , "High",
WriteIf(lowVolume , "Low", "Average")))) + " " +
// spread
EncodeColor(colorBlack) + "Spread: " +
WriteIf(wideRange , EncodeColor(colorBlue) + "Wide",
WriteIf(narrowRange , EncodeColor(colorLightBlue) + "Narrow",
EncodeColor(colorBlack) + "Average")) + ", " +
EncodeColor(colorBlack) + "Close: " +
WriteIf(upClose , EncodeColor(colorGreen) + "Up",
WriteIf(downClose , EncodeColor(colorRed) + "Down",
EncodeColor(colorBlack) + "Middle")) + EncodeColor(colorBlack) + ",\n" +
EncodeColor(colorBlack) + "Long Term: " +
WriteIf(longTermAvg < Ref(longTermAvg,-1),
EncodeColor(colorRed) + "Down",
WriteIf(longTermAvg == Ref(longTermAvg ,-1),
EncodeColor(colorBlack) + "Flat",
EncodeColor(colorGreen) + "Up")) +
EncodeColor(colorBlack) + ", " + "Med Term: " +
WriteIf(medTermAvg < Ref(medTermAvg ,-1),
EncodeColor(colorRed) + "Down",
WriteIf(medTermAvg == Ref(medTermAvg ,-1),
EncodeColor(colorBlack) + "Flat",
EncodeColor(colorGreen) + "Up")) +
EncodeColor(colorBlack) + ", " + "Short Term: " +
WriteIf(shortTermAvg < Ref(shortTermAvg,-1),
EncodeColor(colorRed) + "Down",
WriteIf(shortTermAvg == Ref(shortTermAvg,-1),
EncodeColor(colorBlack) + "Flat",
EncodeColor(colorGreen) + "Up")) +
EncodeColor(colorBlack) + "\n" +
WriteIf(MAvgDirTrend == 1, "Up", "") +
WriteIf(MAvgDirTrend == 0, "No Direction", "") +
WriteIf(MAvgDirTrend == -1, "Down", "");
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%)",
O, H, L, C, SelectedValue( ROC( C, 1 ) )) + "\n" + Dir);
_SECTION_END();
TIP FOR Bullscript users...
Keep in mind that it is still a work in progress. I am somewhat happy with it.
Couple of suggestion though...
Change assignment statements from = to :=
for example...
X = Y;
becomes
X := Y;
Since it (Bullscript) uses Pascal style assignments, you would probably change != to <> and == to = and call to Ref get convered to Hist. Another example (Joels script...)
NoDemand = C>Ref(C,-1) AND V<Ref(V,-1) AND V<Ref(V,-2);
NoDemand2 = C==Ref(C,-1) AND V<Ref(V,-1) AND V<Ref(V,-2) AND Ref(C,-1)>Ref(C,-2);
NoSupply = C<Ref(C,-1) AND V<Ref(V,-1) AND V<Ref(V,-2);
NoSupply2= C==Ref(C,-1) AND V<Ref(V,-1) AND V<Ref(V,-2) AND Ref(C,-1)<Ref(C,-2);
The corresponding bullscript should (?) like
NoDemand := C>Hist(C,1) AND V<Hist(V,1) AND V<Hist(V,2);
NoDemand2 := C=Hist(C,1) AND V<Hist(V,1) AND V<Hist(V,2) AND Hist(C,1)>Hist(C,2);
NoSupply := C<Hist(C,1) AND V<Hist(V,1) AND V<Hist(V,2);
NoSupply2:= C=Hist(C,1) AND V<Hist(V,1) AND V<Hist(V,2) AND Hist(C,1)<Hist(C,2);