_SECTION_BEGIN("Continous Contract");
/*
///////////////////////////////////////////////////////////////////////////
// Continious Contract Rollover
//
// This chart is used to generate a Continuous Contract Rollover ticker
// This chart runs on a 5 second database --not tested on other timeframes
//
// Instructions:
//
// 1. Create a new ticker for the new contract
// 2. Fill in the information section of the new ticker
// 3. Backfill the new ticker with as much data as available
// 4. Run this AFL on the old contract ticker and backfill it if needed
// 5. Turn off all filtering in the database settings
// 6. Set the chart timeframe to match the database base timeframe
// 7. Fill in the parameter for the NEW contract ticker
// 8. Select the rollover date desired
// 9. Verify higher volume for new contract on that date in the chart
//10. Click the parameter to write out the new merged contract text file
//11. Use Import Wizard to import the data into the database
//12. If you mess up, delete the new ticker from the database and start over
//
// The timeframe must match the database or some data will be lost (5 sec)
// All 24 hour data must be selected in the database or some data will be lost
//
// It merges actual contract prices of two tickers
// The old ticker is the one set up in the chart
// The new ticker is selected via parameter
// The rollover date is selected via paramater
// Volumes of both tickers are shown to verify the rollover time
// Tick size, Point value, etc. are copied from the older ticker
// Older contract prices are adjusted down by the premium and appended to the new ticker
// Volumes are just used directly, but it would be better to add them if a RT solution was available for trading that way
//
//
// The new ticker is written out as a textfile
// Once the ticker is generated it must be imported to the database
// This will replace the new ticker data and updates can this happen normally
// One caution is backfilling during the first [provider backfill history days] after the rollover date
// may cause the old contract data (esp. volumes) to be altered which may affect backtest results
// and the whole process would have to be repeated to restore the proper history again
//
// Each contract ticker that is desired to have a long history requires going through this process
// one by one at each rollover date, which may be monthly, bi-monthly, or quarterly
//
///////////////////////////////////////////////////////////////////////////
*/
Version(5.0); //minimum version required
/*
//================================================================
// Draw a Button/Table Cell
// Specify the upper left x,y pixel and size of the cell and the formatting
// Can also specify the row and column number if part of an array of cells
// A text only box with or without a background can be drawn by LineSize=0
//
// TextAlign formatting codes
// AlignTop=0; AlignLeft=0; AlignHCenter=1; AlignRight=2; AlignVCenter=4; AlignBottom=8;
// FmtWordBrk=16; Fmt1Line=32; FmtTabs=64; FmtNoClip=256; FmtNoPrefix=2048;
// FmtEndEllipsis=32768; FmtPathEllipsis=16384;
//
// TextType codes
// Default(0) PointSize=Height/2; PointSize=4-63; Bold=64; Italic=256; Underline=512;
*/
colorClear = ColorRGB(254,254,254); //not quite white, call it a transparent flag
procedure DrawCell(x, y, Width, Height, Col, Row, CellColor, CellText, TextColor, TextType, TextAlign, LineColor, LineSize){
x1 = x + Width*Col;
x2 = x1 + Width;
y1 = y + Height*Row;
y2 = y1 + Height;
// draw a filled solid color rect
if(CellColor!=colorClear){
GfxSelectPen(LineColor, LineSize, none=5);
GfxSelectSolidBrush(CellColor);
GfxSetBkMode(solid=2);
GfxRectangle(x1, y1, x2+1, y2+1);
}
//draw in the text
PointSize = TextType&63;
if(PointSize==0){PointSize = Height/2;}
if(TextType&64){TextWeight = 700;}else{TextWeight = 400;}
if(TextType&256){italic = 1;}else{ italic = 0;}
if(TextType&512){underline = 1;}else{ underline = 0;}
GfxSelectFont( "Tahoma", PointSize, TextWeight, italic, underline, orientation = 0 );
GfxSetTextColor(TextColor);
GfxSetBkMode(transparent=1);
if((TextAlign&1)==1){GfxDrawText(CellText, x1, y1, x2, y2, TextAlign);} //centered
if((TextAlign&2)==2){GfxDrawText(CellText+" ", x1, y1, x2, y2, TextAlign);} //right
if((TextAlign&3)==0){GfxDrawText(" "+CellText, x1, y1, x2, y2, TextAlign);} //left
//draw outlines of box
if(LineSize>0){
GfxSelectPen(LineColor, LineSize);
offset = round(LineSize/2) - 1;
GfxMoveTo(x1+offset, y1+offset);
GfxLineTo(x2-offset, y1+offset);
GfxLineTo(x2-offset, y2-offset);
GfxLineTo(x1+offset, y2-offset);
GfxLineTo(x1+offset, y1+offset);
}
}
///////////////////////////////////////////////////////////////////////////
// RataDieNum and Time Functions mostly copied from the AB UKB
//
function DateNumberToRataDie( DateNumber ){ //modified from the AB UKB --added round()
num = DateNumber/10000;
yyyy = int(num) + 1900;
num = frac(num) * 100;
mm = int(num);
dd = frac(num)*100;
yyyy = yyyy + int((mm-14)/12);
mm = IIf(mm < 3, mm+12, mm);
RataDieNum = round(dd + int((153*mm-457)/5) + 365*yyyy + int(yyyy/4) - int(yyyy/100) + int(yyyy/400) - 306);
return (RataDieNum);
}
///////////////////////////////////////////////////////////////////////////
// Main routine
//
GraphZOrder=1;
GraphXSpace=20;
Lastbar = BarCount-1;
OldContract = Name();
NewContract = ParamStr("New Ticker Symbol","TICKER");
RollDate = ParamDate("Rollover Date","6/12/2008");
writeit = ParamTrigger("Write New Ticker","Click to Make .txt File");
timeBase = Interval(); //5 second database, but could be 15 sec or 60 sec also
BarsIn3hr = 10800/timeBase;
Vxover = 0;
barDates = DateNum();
Plot(C, "OldTicker", colorLightGrey, styleBar);
if( SetForeign(NewContract) AND timeBase > 0){ //newer ticker OHLCV
O1=O; H1=H; L1=L; C1=C; V1=V; //pick up the new ticker data
Plot( C, "NewTicker", colorRed, styleBar);
RestorePriceArrays(); //Back to the old ticker data again
NewV = round(MA(V1,BarsIn3hr));
OldV = round(MA(V,BarsIn3hr));
TotalV = 20*round(LastValue(MA(V,360000/timeBase))); //10 days volume average for chart scale
Plot(OldV, "OldVolume", colorDarkGrey, styleThick|styleOwnScale,0,TotalV);
Plot(NewV, "NewVolume", colorRed, styleNoTitle|styleNoLabel|styleThick|styleHistogram|styleOwnScale,0,TotalV);
Plot(OldV, "OldVolume", colorLightGrey, styleNoTitle|styleNoLabel|styleHistogram|styleOwnScale,0,TotalV);
Plot(NewV, "NewVolume", colorDarkRed, styleThick|styleOwnScale,0,TotalV);
diff = MA((H+L)/2,BarsIn3hr*4) - MA((H1+L1)/2,BarsIn3hr*4); //12 Hour average price difference
tick = TickSize;
Vxover = barDates > RollDate; //find the rollover bar, at midnight
for(i=LastBar; i>0 AND Vxover[i]; I--){;} // find rollover bar
rolloverBar = i;
delta = round(diff[i]*(1/tick))/(1/tick); //move the premium offset to closest tick
O -= delta; H -= delta; L -= delta; C -= delta; // offset old ticker data by premium
for(i=LastBar; i>=0 AND Vxover[i]; I--){ // substitute new ticker data after rollover date
O[i] = O1[i]; H[i] = H1[i]; L[i] = L1[i]; C[i] = C1[i]; V[i] = V1[i];
}
}
Vxover[LastBar] = 2;
Plot(C, "RolledPrice", IIf(Vxover,colorRed,colorBlue), styleBar|styleNoLabel);
if(writeit){
if(OldContract != NewContract ){
bars=0;
filename = NewContract + ".txt";
fh = fopen(filename, "w");
if(fh){
barTimes = TimeNum();
StaticVarSetText("lastfile"+GetChartID(),"Error: endless loop detection preference is set to low");
for(i=0; i<=LastBar; i++){
Yr = int(barDates[i]/10000 +1900);
MoY = int(barDates[i]/100%100);
doM = int(barDates[i]%100);
Hours = int(barTimes[i]/10000);
Minutes = int(barTimes[i]/100%100);
Seconds= int(barTimes[i]%100);
line = StrFormat("%04.0f-%02.0f-%02.0f,%02.0f:%02.0f:%02.0f,%1.2f,%1.2f,%1.2f,%1.2f,%1.0f\n",
Yr, MoY, DoM, Hours, Minutes, Seconds, O[i], H[i], L[i], C[i], V[i]);
fputs( line, fh ); //"2007-12-21,13:41:55,1510.25,1510.00,1510.75,1510.50,20"
bars++;
}
fclose( fh );
}
else {filename = "Error opening "+filename;}
StaticVarSet("Bars"+GetChartID(),bars);
StaticVarSet("WrittenDays"+GetChartID(),DateNumberToRataDie(barDates[LastBar])-DateNumberToRataDie(barDates[0]));
StaticVarSetText("lastfile"+GetChartID(),filename);
}
else {StaticVarSetText("lastfile"+GetChartID(),"Aborted Overwrite of Old Ticker");}
}
//Make a box of legends
CellText =
" Continious Contract Rollover Maker: \n"+
" --Light Grey: Old contract Price \n"+
" --Red: New contract Price \n"+
" --Blue: Adjusted old contract Price \n"+
" --Dark Grey: Old contract volume \n"+
" --Dark Red: New contract volume \n"+
" (Volumes are 3 hr average contracts/bar) \n\n";
DrawCell(0, 20, 350, 130, 0, 0, colorWhite, CellText, colorBlack, 10, 256, colorBlack, 1);
//Make a box of status
barsWritten = NumToStr(StaticVarGet("Bars"+GetChartID()),1.0);
daysWritten = NumToStr(StaticVarGet("WrittenDays"+GetChartID()),1.0);
lastFile = StaticVarGetText("lastfile"+GetChartID());
CellText =
" Last Operation Status: \n\n"+
" "+daysWritten +" Total days written to file \n"+
" "+barsWritten +" Total bars written to file \n"+
" Last file written: "+lastFile;
DrawCell(0, 150, 350, 100, 0, 0, colorWhite, CellText, colorBlack, 10, 256, colorBlack, 1);
//Make a box of instructions
CellText =
" Instructions: \n\n"+
" 1. Create a new ticker for the new contract \n"+
" (Quarterly contracts progress: H7 M7 U7 Z7 H8...) \n"+
" 2. Fill in the information section of the new ticker \n"+
" 3. Backfill the new ticker with as much data as available \n"+
" 4. Run this AFL on the old contract ticker and backfill \n"+
" 5. Turn off all filtering in the database settings \n"+
" 6. Set the chart to match the database base timeframe \n"+
" 7. Fill in the parameter for the NEW contract ticker \n"+
" 8. Select the rollover date parameter \n"+
" 9. Verify higher volume for new contract on that date \n"+
" 10. Click param to write out the new contract text file \n"+
" 11. Use Import Wizard to import the data into the database \n"+
" (Format: YMD, Time, O, H, L, C, V)\n"+
" 12. If you goof, delete the new ticker and start over \n\n"+
" Backfilling during the first provider backfill-history-days \n"+
" after the rollover date may alter the old contract data \n"+
" and the whole process will have to be repeated ";
//
DrawCell(0, 250, 350, 340, 0, 0, colorWhite, CellText, colorBlack, 10, 256, colorBlack, 1);
RequestTimedRefresh(5,0);
SetBarsRequired(1000000,1000000);
_SECTION_END();