{ Alan Box Draw Object by TerryT and Quartz } {version 2005 05 21} { To create } { Run ESPL 21 } { Drag a 2 pt line to set high, low, begin, end } { Click once more outside the line to complete initial input } { To edit } { Click on the high-start pt or the low-end pt to select the object } { Then edit the box the same way to you would an ensign draw line object } { Uses tab 14 for line colors and some style info (vert, .25&.75, .50, 2H&H&L&2L, upAng, dnAng) } { picking the last line style for the upAng or dnAng is special cased to draw dotted angulars way amg sometimes does } { known problems } { When I forced the box to avoid drawing the start or end between bars, I got drawing turds. } { So the box jumps a slight bit when deselected after dragging } var gWasSelected :integer; gStudyName :string; procedure getFormatSpec( sym :string ) :real; var fmtSpec :real; begin fmtSpec := 4.2; if (LeftStr(sym,3)='@ES') OR (LeftStr(sym,2)='ES') then fmtSpec := 4.2 else if (LeftStr(sym,3)='@YM') OR (LeftStr(sym,2)='YM') then fmtSpec := 5.0 else if LeftStr(sym,3)='EUR' then fmtSpec := 1.4 else if LeftStr(sym,2)='NQ' then fmtSpec := 4.2 else if LeftStr(sym,2)='AB' then fmtSpec := 5.0 else if LeftStr(sym,4)='ER2' then fmtSpec := 3.1 else if LeftStr(sym,5)='GBL' then fmtSpec := 3.2; Result := fmtSpec; end; Procedure HHMMToMinutes( time :integer ) :integer; var h, m :integer; begin h := trunc(time /100); m := time - 100*h; Result := m+60*h; end; Procedure MinutesToHHMM( minutes :integer ) :integer; var h, m :integer; begin h := trunc(minutes /60); m := minutes - 60*h; Result := m+100*h; end; procedure QuantizeTime( BarMinutes, BarTime :integer ) :integer; var t :integer; begin t := HHMMToMinutes( BarTime ); t := BarMinutes*trunc( ( t + BarMinutes - 1) / BarMinutes); Result := MinutesToHHMM(t); end; procedure QuantizePrice( price :real ) :real; var minTick :real; begin minTick := GetVariable(eTick); Result := minTick*round(price / minTick); end; procedure DrawStrLeft( s :string; x, y, lastX, lastY :real; fh :integer); begin if 0 <> IsSelected then begin if (0 <> lastX) then begin SetBrush(GetVariable(eColorChart),eSolid); TextOut( lastX-TextWidth(s)-10, lastY-fh, s ); end; end else begin TextOut( x-TextWidth(s)-10, y-fh, s ); end; end; procedure DrawStrRight( s :string; x, y, lastX, lastY :real; fh :integer); begin if 0 <> IsSelected then begin if (0 <> lastX) then begin SetBrush(GetVariable(eColorChart),eSolid); TextOut( lastX+10, lastY-fh, s ); end; end else begin TextOut( x+10, y-fh, s ); end; end; procedure MySetPen( color, style :integer ); begin if style = 0 then SetPen(color,1,eHidden); if (style > 0) AND (style < 6) then SetPen(color,style,eSolid); if style > 5 then SetPen(color,1,eDot); end; procedure drawABox( x1, y1, x2, y2 :real ); var sX, H, eX, L, lastX1, lastY1, lastX2, lastY2, priceRange, priceRange2, priceRange4, tmp :real; HH, a2, b2, c2, a1, b1, c1, a0, b0, c0, LL, fh, range :real; s :string; amgAngularStyleP :boolean; highPrice, lowPrice :real; vertColor, highColor, lowColor, oddQColor, halfColor, upAngColor, dnAngColor :integer; vertStyle, highStyle, lowStyle, oddQStyle, halfStyle, upAngStyle, dnAngStyle :integer; fmtDigits, fmtFracDigits :integer; begin vertColor := GetStudy( 0, 50 ); // get vert line color oddQColor := GetStudy( 0, 50+1 ); // get .25 .75 line color halfColor := GetStudy( 0, 50+2 ); // get .5 line color highColor := GetStudy( 0, 50+3 ); // get H L line color lowColor := highColor; upAngColor := GetStudy( 0, 50+4 ); // get up angular line color dnAngColor := GetStudy( 0, 50+5 ); // get dn angular line color vertStyle := GetStudy( 0, 110 ); // get vert line style oddQStyle := GetStudy( 0, 110+1 ); // get .25 .75 line style halfStyle := GetStudy( 0, 110+2 ); // get .5 line style highStyle := GetStudy( 0, 110+3 ); // get H L line style lowStyle := highStyle; upAngStyle := GetStudy( 0, 110+4 ); // get up angular line style dnAngStyle := GetStudy( 0, 110+5 ); // get dn angular line style amgAngularStyleP := false; if (upAngStyle =9) or (dnAngStyle =9) then amgAngularStyleP := true; // grab these to display numbers in the fixed old locations while dragging tmp := 0.000001+GetStudy(0,36); // price format spec fmtDigits := trunc(tmp); fmtFracDigits := trunc(10*(tmp - fmtDigits)); //writeln( tmp, ' ', fmtDigits, ' ', 10*(tmp-fmtDigits), ' ', fmtFracDigits); lastX1 := GetStudy(0,37); // last start position lastY1 := GetStudy(0,38); // last high position lastX2 := GetStudy(0,39); // last end position lastY2 := GetStudy(0,40); // last low position fh := GetVariable(eFontSize); // just use the chart's font size (since changing it and restoring it causes an endless loop) // prices for text output highPrice := GetStudy(0,25); // current high price from Pt1 (start) lowPrice := GetStudy(0,26); // current low price from Pt2 (end) priceRange := highPrice - LowPrice; priceRange4 := priceRange/4; priceRange2 := priceRange/2; // screen coordinates sX := x1; eX := x2; H := y1; L := y2; range := H-L; //writeln( 'Draw ', sX,' ',H,' ',eX,' ',L ); a1 := H - (range/4); b1 := H - (range/2); c1 := L + (range/4); HH := H +range; a2 := a1 +range; b2 := b1 +range; c2 := c1 +range; a0 := a1 -range; b0 := b1 -range; c0 := c1 -range; LL := L -range; MySetPen(vertColor,vertStyle); MovetoLineto(sX,HH,sX,LL); { vert line at beginning } //MovetoLineto((eX+sX)/2,HH,(eX+sX)/2,LL); { vert line at middle } MovetoLineto(eX,HH,eX,LL); { vert line at end } MySetPen(highColor,highStyle); MovetoLineto(sX,HH,eX,HH); { hor line HH } MovetoLineto(sX,H,eX,H); { hor line H } Ellipse(sX-5,H+5,sX+5,H-5); { circle at start,high } Str( highPrice+priceRange,fmtDigits,fmtFracDigits,s); // Upper DrawStrLeft( s, sX, HH, 0, 0, fh ); DrawStrRight( '2.0', eX, HH, 0, 0, fh ); Str( highPrice,fmtDigits,fmtFracDigits,s); // High DrawStrLeft( 'H '+s, sX, H, lastX1, lastY1, fh ); DrawStrRight( '1.0', eX, H, lastX2, lastY1, fh ); MySetPen(lowColor,lowStyle); MovetoLineto(sX,L,eX,L); { hor line L } MovetoLineto(sX,LL,eX,LL); { hor line LL } Ellipse(eX-5,L+5,eX+5,L-5); { circle at end,low } Str( lowPrice,fmtDigits,fmtFracDigits,s); // Low DrawStrLeft( 'L '+s, sX, L, lastX1, lastY2, fh ); DrawStrRight( '0.0', eX, L, lastX2, lastY2, fh ); Str( lowPrice-priceRange,fmtDigits,fmtFracDigits,s); // Lower DrawStrLeft( s, sX, LL, 0, 0, fh ); DrawStrRight( '-1.0', eX, LL, 0, 0, fh ); MySetPen(halfColor,halfStyle); MovetoLineto(sX,b2,eX,b2); { hor line b2 } MovetoLineto(sX,b1,eX,b1); { hor line b1 } MovetoLineto(sX,b0,eX,b0); { hor line b0 } Str( highPrice+priceRange2,fmtDigits,fmtFracDigits,s); // Upper 50% DrawStrLeft( s, sX, b2, 0, 0, fh ); DrawStrRight( '1.50', eX, b2, 0, 0, fh ); Str( highPrice-priceRange2,fmtDigits,fmtFracDigits,s); // Mid 50% DrawStrLeft( s, sX, b1, 0, 0, fh ); DrawStrRight( '.50', eX, b1, 0, 0, fh ); Str( lowPrice-priceRange2,fmtDigits,fmtFracDigits,s); // Lower 50% DrawStrLeft( s, sX, b0, 0, 0, fh ); DrawStrRight( '.50', eX, b0, 0, 0, fh ); MySetPen(oddQColor,oddQStyle); MovetoLineto(sX,a2,eX,a2); { hor line a2 } MovetoLineto(sX,a1,eX,a1); { hor line a1 } MovetoLineto(sX,a0,eX,a0); { hor line a0 } MovetoLineto(sX,c2,eX,c2); { hor line c2 } MovetoLineto(sX,c1,eX,c1); { hor line c1 } MovetoLineto(sX,c0,eX,c0); { hor line c0 } Str( highPrice+priceRange-priceRange4,fmtDigits,fmtFracDigits,s); // Upper 75% DrawStrLeft( s, sX, a2, 0, 0, fh ); DrawStrRight( '1.75', eX, a2, 0, 0, fh ); Str( highPrice-priceRange4,fmtDigits,fmtFracDigits,s); // Mid 75% DrawStrLeft( s, sX, a1, 0, 0, fh ); DrawStrRight( '.75', eX, a1, 0, 0, fh ); Str( lowPrice-priceRange4,fmtDigits,fmtFracDigits,s); // Lower 75% DrawStrLeft( s, sX, a0, 0, 0, fh ); DrawStrRight( '.75', eX, a0, 0, 0, fh ); Str( highPrice+priceRange4,fmtDigits,fmtFracDigits,s); // Upper 25% DrawStrLeft( s, sX, c2, 0, 0, fh ); DrawStrRight( '0.25', eX, c2, 0, 0, fh ); Str( lowPrice+priceRange4,fmtDigits,fmtFracDigits,s); // Mid 25% DrawStrLeft( s, sX, c1, 0, 0, fh ); DrawStrRight( '.25', eX, c1, 0, 0, fh ); Str( lowPrice-priceRange+priceRange4,fmtDigits,fmtFracDigits,s); // Lower 25% DrawStrLeft( s, sX, c0, 0, 0, fh ); DrawStrRight( '.25', eX, c0, 0, 0, fh ); if amgAngularStyleP then MySetPen(dnAngColor,1) else MySetPen(dnAngColor,dnAngStyle); MovetoLineto(sX,b2+range,eX,b2); { downdiag to b2 } MovetoLineto(sX,b2,eX,b2-range); { downdiag from b2 } MovetoLineto(sX,b1,eX,b1-range); { downdiag from b1 } MovetoLineto(sX,b0,eX,b0-range); { downdiag from b0 } if amgAngularStyleP then MySetPen(dnAngColor,66) else MySetPen(dnAngColor,dnAngStyle); MovetoLineto(sX,HH,eX,HH-range); { downdiag from HH } MovetoLineto(sX,H ,eX,H -range); { downdiag from H } MovetoLineto(sX,L ,eX,L -range); { downdiag from L } if amgAngularStyleP then MySetPen(upAngColor,1) else MySetPen(upAngColor,upAngStyle); MovetoLineto(sX,b2,eX,b2+range); { updiag from b2 } MovetoLineto(sX,b1,eX,b1+range); { updiag from b1 } MovetoLineto(sX,b0,eX,b0+range); { updiag from b0 } MovetoLineto(sX,b0-range,eX,b0); { updiag to b0 } if amgAngularStyleP then MySetPen(upAngColor,6) else MySetPen(upAngColor,upAngStyle); MovetoLineto(sX,H ,eX,H +range); { updiag from H } MovetoLineto(sX,L ,eX,L +range); { updiag from L } MovetoLineto(sX,LL,eX,LL+range); { updiag from LL } if IsSelected = 0 then begin // store these for drawing numbers in same spot while selected. SetStudy(0,37,sX); // store start position SetStudy(0,38,H); // store high position SetStudy(0,39,eX); // store end position SetStudy(0,40,L); // store low position end; end; procedure makeAlanObject; var hdl,startI,endI,tabNum :integer; hPrice, lPrice, t :real; begin tabNum := 14; // do the right thing no matter what direction the user dragged // and force the prices to a multiple of min tick for the symbol hPrice := QuantizePrice(YToPrice(Pt1Y)); lPrice := QuantizePrice(YToPrice(Pt2Y)); if lPrice > hPrice then begin t := hPrice; hPrice := lPrice; lPrice := t; end; startI := XToIndex(Pt1X); endI := XToIndex(Pt2X); if startI > endI then begin t := endI; endI := startI; startI := t; end; // ok add the box (3rd pt is unused and placed somewhere out of the way) hdl := AddLine( eESPLTool, tabNum, startI, hPrice, endI, lPrice, endI, 1 ); SetStudy( hdl, 17, 'init Alan Box' ); // name //SetStudy( hdl, 11, ESPLNum ); // set ESPL number OOPS! this call does nothing SetStudy(0,36, getFormatSpec(GetVariable(eSymbol))); // store price format spec // help user see which colors go to which lines by leaving these unused hints SetStudy( 0, 31, 25 ); // set level SetStudy( 0, 32, 50 ); // set level SetStudy( 0, 33, 100 ); // set level SetStudy( 0, 34, 1 ); // set level SetStudy( 0, 35, -1 ); // set level //writeln( 'create' ); end; procedure initAlanObject(); begin // set name SetStudy( 0, 17, 'Boxinacci' ); // force it to draw Refresh(); //writeln( 'init'); end; procedure QuantizeY(); var p :real; begin // force prices to a multiple of min tick p := QuantizePrice(YToPrice(pt1Y)); SetStudy( 0, 25, p ); // set high price pt1Y := PriceToY( p ); // draw there now p := QuantizePrice(YToPrice(pt2Y)); SetStudy( 0, 26, p ); // set low price pt2Y := PriceToY( p ); // draw there now end; procedure QuantizeX(); var i :integer; begin // force position to a bar i := XToIndex(pt1X); SetStudy(0,6,i); // set start index pt1X := IndexToX(i); // draw there now i := XToIndex(pt2X); SetStudy(0,7,i); // set end index pt2X := IndexToX(i); // draw there now end; procedure drawAlanObject(); begin // user is dragging around if IsSelected <> 0 then begin gWasSelected := 1; QuantizeY; //QuantizeX; // this causes drawing turds end; // user just stopped dragging around if (IsSelected = 0) AND (gWasSelected > 0) then begin gWasSelected := gWasSelected -1; QuantizeY; QuantizeX; Refresh(True); //writeln( 'deselect refresh'); end; // ok. finally draw the studpid thing DrawABox( Pt1X, Pt1Y, Pt2X, Pt2Y ); //writeln( 'Boxinacci ', IsSelected ); end; {********** Main Program **********} begin // Run ESPL 21 to drag your own thing if ESPL= 21 then makeAlanObject; // I can't seem to set the ESPL number of an eESPLTOOL created with AddLine // so I am dispatching to the proper routine based on the study's name if ESPL= 11 then begin gStudyName := GetStudy( 0, 17 ); if ('Boxinacci' = RightStr( gStudyName, 9)) then drawAlanObject else if ('init Alan Box' = RightStr( gStudyName, 13)) then initAlanObject; end; end;