[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Sharpe Ratios of CTA's



PureBytes Links

Trading Reference Links

: Bob Fulkes writes of Sharpe ratios of mechanical systems.

Attached is a ELA written by Bob Fulkes, with the function outline below. It
calculates the Sharpe Ratio as a function to be used in an indicator...to be
used in conjunction with a system. I find it to be very useful and I want to
thank Bob for it.

{Function: SharpeRatio}

{ *******************************************************************

 Function  : SharpeRatio

 Last Edit  : 11/24/98

 Provided By : Bob Fulks

 Description : This function calculates and returns the Sharpe Ratio
  of a series of account values. It samples the series of values
  on a yearly, quarterly, monthly, weekly, or daily basis as
  determined by an input. It also calculates average return and
  standard deviation. It prints the results in a form suitable for
  importing into an Excel spreadsheet for plotting.

 Inputs:
  Mode - Sampling period (0=yearly, 1=quarterly, 2=monthly,
   3=weekly, 4=daily
  NetValue - The series of values to be sampled. It should be
   equal to the beginning equity plus accumulated net profits.
  Periods - The number of yearly, quarterly, etc., periods to
   include in the calculation. If this value is zero, the
   function will use all periods up to a maximum of 1500.
  PrntMode:
   zero   - Print one line summary only on last bar
   > zero - Print values as stored in array plus summary
   < zero - Do not print anything
  Futures:
   TRUE  - For futures trading (Sharpe = Ave / SDev)
   FALSE - For Stocks (Sharpe = (Ave - 5) / SDev)

 Method: The function samples the value of the trading account at
  periodic intervals, calculates returns in each period, then
  calculates the average and standard deviation of returns and
  annualizes them. It then calculates to Sharpe Ratio as noted
  above.

 Assumptions: The usage for stocks assumes a constant value of 5%
  for the risk-free return (T-Bill interest rate). This is a good
  assumption for recent times but may be incorrect for the distant
  past. The Sharpe Ratio is independent of the sampling interval
  if the returns are normally distributed. Returns are typically
  not strictly normally distributed so the sampling interval will
  affect the results somewhat. There should be more than about 25
  samples to get reasonable accuracy so use daily samples for 1
  to 6 months of trades, weekly samples for 6 months to 24 months
  of trades, etc.


  © 1998 Robert G. Fulks, All rights reserved.

********************************************************************}

Input: Mode(NumericSimple),
    {0=yearly, 1=quarterly, 2=monthly, 3=weekly, 4=daily}
   NetValue(NumericSimple),
    {Net value of account = Beginning Equity + NetProfit}
   Periods(NumericSimple),
    {Number of periods to use in calculation, zero = all}
   PrntMode(NumericSimple),
    {0 = print summary, 1 = include detail, -1 = don't print}
   Futures(TrueFalse);
    {TRUE for Futures, FALSE for Stocks}

Vars:  Index(0),    {Index used to index Return array}
   SIndex(0),    {Index used to sum Return array}
   LNetVal(0),    {NetValue at end of previous period}
   LClose(0),   {Close at end of previous period}
   YClose(0),   {Close at end of previous bar}
   Size(0),    {Sixe of data to be stored in array}
   ILast(0),     {Number of entries in array}
   Ave(0),     {Average return}
   ASum(0),     {Used to calc Average}
   SSum(0),     {Used to calc Standard Deviation}
   SDev(0),     {Standard Deviation}
   SDMult(0),    {Multiplier to annualize Standard Deviation}
   Mo(0),      {Month for bar}
   MP(0),    {MarketPosition}
   MPX(0),    {MarketPosition flag becomes 1 on first trade}
   YMo(0),    {Month for previous bar}
   Yr(-99),    {Year for bar}
   YYr(0),    {Year for previous bar}
   YDate(0),   {Date for previous bar}
   AvMult(0),    {Multiplier to annualize Average}
   NetVal(0),    {NetValue series}
   YNetVal(0),   {Netval for previous bar}
   Active(FALSE),   {False for first calc then true thereafter}
   Record(FALSE),   {Flag to trigger calculation at end of period}
   Summary(FALSE),   {Flag set if summary printed}
   StDate(0),   {Start date}
   Sharpe(0);    {Sharpe Ratio}

Array: Return[1500](0);  {Table of returns as a percent}

Size   = iff(Periods > 0, Periods, 1500);
Size   = MinList(Size, 1500);
NetVal = Netvalue;
Mo     = Month(Date);
Yr     = Year(Date);

{This determines marketposition in either systems or indicators}
if MarketPosition <> 0 then
 MP = MarketPosition
else
 MP = I_MarketPosition;

MPX = iff(MP <> 0, 1, MPX);

Condition1 = Mo = 1 or Mo = 4 or Mo = 7 or Mo = 10;

begin

 {Initialize for yearly}

 if Mode = 0 and Yr <> YYr then begin
  SDMult  = 1;
  AvMult  = 1;
  Record  = TRUE;
 end;

 {Initialize for quarterly}

 if Mode = 1 and Mo <> YMo and Condition1 then begin
  SDMult  = 2;
  AvMult  = 4;
  Record  = TRUE;
 end;

 {Initialize for monthly}

 if Mode = 2 and Mo <> YMo then begin
  SDMult  = SquareRoot(12);
  AvMult  = 12;
  Record  = TRUE;
 end;

 {Initialize for weekly}

 if Mode = 3 and DayOfWeek(Date) < DayOfWeek(YDate) then begin
  SDMult  = SquareRoot(52);
  AvMult  = 52;
  Record  = TRUE;
 end;

 {Initialize for daily}

 if Mode = 4 and Date <> YDate then begin
  SDMult  = SquareRoot(253);
  AvMult  = 253;
  Record  = TRUE;
 end;
end;

{Action if new year, quarter, month, week, or day}

if Record = TRUE then begin
 if Active = TRUE then begin
  {Each time except first time}
  begin
   ILast = ILast + 1;
   if LNetVal <> 0 then Value1 = YNetVal / LNetVal;
   if Value1 > 0 then Return[Index] = 100 * Log(Value1);
   if PrntMode > 0 then Print(Index:5:0, Date:7:0, YClose:6:2,
    LClose:6:2, YNetVal:7:0, LNetVal:7:0, Return[Index]:4:2);
   Index = Mod(Index + 1, Size);
  end;
 end else
  {First time only after initial position}
  if MPX > 0 then begin
   Active = TRUE;
   StDate = Date;
   if PrntMode > 0 then Print(Index:5:0, Date:7:0, YClose:6:2,
    LClose:6:2, YNetVal:7:0, LNetVal:7:0, Return[Index]:4:2);
  end;

 LClose  = YClose;
 LNetVal = YNetVal;
 Record  = FALSE;
end;

{Calculate and print summary}

if Active = TRUE and Summary = FALSE and
 (LastBarOnChart or ILast >= Size) then begin

 {Calculate average return in period}
 Summary = TRUE;
 ASum = 0;
 ILast = MinList(Size, ILast);
 for SIndex = 0 to ILast - 1 begin
  ASum = ASum + Return[SIndex];
 end;
 Ave = ASum / ILast;

 {Calculate annualized standard deviation}
 SSum = 0;
 for SIndex = 0 to ILast - 1 begin
  SSum = SSum + Square(Return[SIndex] - Ave);
 end;
 SDev = SDMult * SquareRoot(SSum / ILast);

 {Annualize average}
 Ave  = AvMult * Ave;

 {Convert back to ratios from logarithms}
 SDev = 100 * (ExpValue(SDev / 100) - 1);
 Ave  = 100 * (ExpValue(Ave  / 100) - 1);

 {Calculate Sharpe Ratio}
 if SDev <> 0 then begin
  if Futures then
   Sharpe = Ave / SDev
  else
   Sharpe = (Ave - 5) / SDev;
 end;

 if PrntMode >= 0 then
  Print( ",", StDate:6:0, ",", ILast:6:0, ",", SDev:6:1, "%,", Ave:6:1,
"%,",
  Sharpe:3:2, ",  ",GetSymbolName, ",");

end;

{Print(Date:6:0, NetVal, Sharpe:4:2, MP:2:0, Active);}

YMo     = Mo;
YYr     = Yr;
YDate   = Date;
YClose  = Close;
YNetVal = NetVal;

SharpeRatio = Sharpe;