Need help programming my Pairs system in TS

Discussion in 'Strategy Development' started by hmap1, Jan 24, 2003.

  1. hmap1

    hmap1

    Hello, I am new to Tradestation. As of right now, I am good at tweaking existing code and modifying from that point. I am still learning as I go. I have a Pairs trading system that I am looking to get turned into code for Tradestation. If anyone can help me out and it seems to work, be my guest to use it. It's a very simple concept that I am looking to expand as I learn about the code. If anyone is interested in writing it, please PM me for the idea. Thanks ahead of time.
     
  2. Foz

    Foz

    What version of Tradestation are you using? I use TS2000i.
     
  3. hmap1

    hmap1

    I use TS6.
    Thanks,
    m
     
  4. You cannot "take the other side" when system testing pairs in TradeStation (TS). TS will only let you buy/sell the primary data, data1. As it stands now, you can't import a spread in either, to attempt to trade it.

    I tried to write a system to test each side of the pair and then mate the results. It was a lot of work and less than satisfactory.

    I got around this by coding an indicator to simulate the buys and sells (recording enty/exit prices, counting trades, etc.) and then directing the output to a window or a file. I then copied over to Excel and ran the statistics.

    I programmed several such crude pair testing indicators in TS6 a few months ago. I never really came across a method that I liked. Unfortunately I lost this work when I dropped TS6 and removed it from my system (dropped back to TS2000i).

    So it can be done, but it's not as straight-forward as one might initially think.
     
  5. qdz2

    qdz2

    Why this can not be done? Or did I miss something? Set up a hypothetical ticker SPREAD:

    bid = bid1 - bid2
    ask = ask1 - ask2
    last = last1 - last2
    volume = min(volme1, volume2)

    It is okay to assume bid1, ask1, last1 is always larger values for the same security.

    Is this a valid idea to get it start?

    :p
     
  6. Don't see why you couldn't program two systems, one for each tradable, based on essentially the same underlying code (with certain terms reversed), with two multi-data charts, one where data(1) was tradable ABC, the other where data(2) was tradable XYZ.

    If the issue is getting backtesting results then you'd have to either combine results on a spreadsheet or use an add-on like the RINASystems ones for portfolio testing.

    There are other possibilities, though some are beyond my programming experience or expertise (such as DLLs and global variables).

    If you PM me the rules, I might take a crack at it. No guarantees though - my experience with EL is that many things that look complicated are actually very simple, but that other things that you'd think would be easy are impossible or close to it.
     
  7. hmap,

    Have you looked at Mark Conway and Aaron Behl's model for pair trading in their book "Professional Stock Trading"? If not, they set up a day-trading pair model incorporating correlation and volatility. If for nothing else, you can see how they programmed theirs. It is all fully disclosed easylanguage. In fact, I'll just post it below. Since TS can only give signals on Data1 you'll have to set up TWO separate charts. The first will be configured as follows:

    Data1: 5 min bars of ABC
    Data2: 5 min bars of XYZ
    Data3: daily bars of ABC
    Data4: daily bars of XYZ


    In the second chart, swap ABC for XYZ like so:

    Data1: 5 min bars of XYZ
    Data2: 5 min bars of ABC
    Data3: daily bars of XYZ
    Data4: daily bars of ABC


    Then apply this strategy to both charts. Here's the code. Good luck!:

    {START HERE -------------------------------------------------------}
    inputs: Price1(close of data3),
    Price2(close of data4),
    StandardDeviations(1.5),
    Length(30),
    {Position Sizing Parameters}
    Equity(48000),
    RiskModel(3),
    RiskPercent(2.0),
    RiskATR(1.0),
    {Trade Logging}
    LogTrades(False),
    LogFile("Orders.txt");
    vars:
    N(0),
    HV1(0.0),
    HV2(0.0),
    CV(0.0),
    VolatilityBand(0.0),
    VolatilityConstant(0.0523),
    UpperBand(0.0),
    LowerBand(0.0),
    Spread(0.0);

    If Date <> Date[1] Then Begin
    N = AcmeGetShares(Equity,RiskModel,RiskPercent,RiskATR,100);
    HV1 = acmevolatility(Length) of Data3;
    HV2 = acmevolatility(Length) of Data4;
    CV = Correlation(Price1,Price2,Length);
    VolatilityBand = VolatilityConstant*(HV1+HV2)*(1-CV);
    UpperBand = StandardDeviations*VolatilityBand;
    LowerBand = StandardDeviations*(-VolatilityBand);
    End;

    Spread = (Close of Data1/Price1)-(Close of Data2/Price2);

    If {time<1495 and time>0840 and} Spread crosses above LowerBand then
    Buy ("PairLE") N Shares This Bar on Close;
    If Spread crosses above 0 {or Time>1495} then
    Sell ("PairLX +") This bar on Close
    Else if Spread <= StandardDeviations*LowerBand Then
    Sell ("PairLX -")this Bar on Close;

    If {time<1495 and time>0840 and} Spread crosses below UpperBand then
    SellShort ("PairSE") N Shares This Bar on Close;
    If Spread crosses below 0 {or Time>1495} then
    BuytoCover("PairSX +") This bar on Close
    Else if Spread >= StandardDeviations*UpperBand Then
    BuyToCover("PairSX -")this Bar on Close;

    {Log Trades for Spreadsheet Export}
    Condition1 = AcmeLogTrades(LogTrades,LogFile,"Pairs");
    {END HERE -------------------------------------------------------}


    Here is the indicator that goes along with it so you can visually see the spread:

    {START HERE -------------------------------------------------------}
    inputs: Price1(close of data3),Price2(close of data4),StandardDeviations(1.5),
    Length(30);
    vars: HV1(0.0),HV2(0.0),CV(0.0),VolatilityBand(0.0),VolatilityConstant(0.0523),
    UpperBand(0.0),LowerBand(0.0),Spread(0.0);

    HV1 = acmevolatility(Length) of Data3;
    HV2 = acmevolatility(Length) of Data4;
    CV = Correlation(Price1,Price2,Length);
    VolatilityBand = VolatilityConstant*(HV1+HV2)*(1-CV);
    UpperBand = StandardDeviations*VolatilityBand;
    LowerBand = StandardDeviations*(-VolatilityBand);
    Spread = (Close of Data1/Price1)-(Close of Data2/Price2);

    Plot1(Spread[1],"Spread");
    Plot2(0,"Zeroline");
    Plot3(UpperBand,"UpperBand");
    Plot4(LowerBand,"LowerBand");

    Here are two functions you'll need (AcmeVolatility and AcmeGetShares):

    {START HERE -------------------------------------------------------}
    {AcmeVolatility}
    inputs: length(numeric);
    variables: DaysinYear(365), DaysInMonth(30),DaysInWeek(7),
    TimeFactor(0.0);

    AcmeVolatility = 0;

    If C>0 and C[1]>0 then Begin
    If DataCompression>=2 and DataCompression<5 Then Begin
    If DataCompression = 2 Then {Daily}
    TimeFactor = DaysInYear
    Else if DataCompression = 3 Then {Weekly}
    TimeFactor = DaysInYear/DaysInWeek
    Else if DataCompression = 4 Then {Monthly}
    TimeFactor = DaysInYear/DaysInMonth;

    AcmeVolatility = StdDev(Log(c/C[1]),Length)*SquareRoot(TimeFactor);
    End;
    End;
    {END HERE -------------------------------------------------------}

    {START HERE -------------------------------------------------------}

    {AcmeGetShares}
    {AcmeGetShares: Calculate the number of shares based on risk model

    RiskModel1 = 1, Equal Value Units Model
    RiskModel2 = 2, Percent Risk Model
    RiskModel3 = 3, Percent Volatility Model
    RiskModel4 = 4, Fixed Number of Contracts}

    Inputs:
    Equity(Numeric),
    RiskModel(Numeric),
    RiskPercent(Numeric),
    RiskUnits(Numeric);

    Variables:
    MinimumShares(100),
    RiskShares(0),
    ERP(0.0),
    Length(20);

    ERP = Equity*RiskPercent/100;

    If RiskModel = 1 and Close>0 then
    RiskShares = Maxlist(MinimumShares,100*IntPortion(Equity/(100*C)));

    If Riskmodel = 2 and RiskUnits>0 then
    RiskShares = Maxlist(MinimumShares,100*intPortion(ERP/(100*RiskUnits)));

    If Riskmodel = 3 and Volatility(length)>0 then
    RiskShares = Maxlist(MinimumShares,100*IntPortion(ERP/(100*Volatility(length))));

    If Riskmodel = 4 then
    RiskShares = RiskUnits;

    AcmeGetShares = RiskShares;
    {END HERE -------------------------------------------------------}
     
  8. Forgot this function:

    {AcmeLogTrades: Log Trades to a file for import into a spreadsheet}

    Inputs:
    LoggingOn(truefalse),
    LogFileName(String),
    SystemID(String);

    Variables:
    ADXLength(14),
    Length(30),
    TradeString("");

    If LoggingOn and Category =2 Then Begin
    {Log Closed Positions}
    If BarsSinceExit(1) =1 then Begin
    Tradestring = GetSymbolName+","+
    NumToStr(EntryDate(1),0)+","+
    NumToStr(EntryPrice(1),3)+","+
    NumToStr(ExitDate(1),0)+","+
    NumToStr(ExitPrice(1),3)+","+
    NumToStr(PositionProfit(1),3)+","+
    NumToStr(ADX(ADXLength)[BarsSinceEntry(1)],0)+","+
    NumToStr(Volatility(Length)[BarsSinceEntry(1)],2)+","+
    NumToStr(AcmeVolatility(Length)[BarsSinceEntry(1)],3)+","+
    SystemID+","+NewLine;
    FileAppend(LogFileName,Tradestring);
    End;
    {Log Open Positions}
    If LastBarOnChart and CurrentEntries > 0 then Begin
    Tradestring = GetSymbolName+","+
    NumToStr(EntryDate(1),0)+","+
    NumToStr(EntryPrice(1),3)+","+
    NumToStr(Date,0)+","+
    NumToStr(Close,3)+","+
    NumToStr(OpenPositionProfit,3)+","+
    NumToStr(ADX(ADXLength)[BarsSinceEntry(1)],0)+","+
    NumToStr(Volatility(Length)[BarsSinceEntry(1)],2)+","+
    NumToStr(AcmeVolatility(Length)[BarsSinceEntry(1)],3)+","+
    SystemID+","+NewLine;
    FileAppend(LogFileName,Tradestring);
    End;
    AcmeLogTrades=True;
    End;
     
  9. You can setup a hypothetical ticker SPREAD., but you can't "trade it" (i.e., system test) an indicator in TS6.

    It is possible to create the ticker and import it into TS2000i.
     
  10. I did some pair testing exactly as you state above, but compiling the results proved worse than just writing an indicator to simulate the trading results (and exporting those).

    RinaSystems could be an excellent product for this application(never used it, though). That's a good idea.

    However, my earlier comments were directed to someone who appears to be a beginner with TS. I just wanted to alert him/her that pair testing was not as straight-forward as for a single issue.
     
    #10     Jan 24, 2003