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.
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.
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?
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.
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 -------------------------------------------------------}
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;
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.
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.