Continuous Contract Rollover System


Continuous Contract Rollover System
Continuous Contract Rollover System


//www.aflcode.com
_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();

Previous
Next Post »