Measuring Leverage

Hi,

C2 provides various measures of Risk, such as Risk of Ruin (Monte-Carlo). However, these are not helpful when measuring potential risk on a futures strategy, particularly if the strategy is new or if the strategy developer has changed his trading strategy recently.

For futures systems, it is very important for subscribers to understand Notional Value and Leverage. As this is not readily available on the grid, we developed C2Explorer code for our in-house use and also decided to put it out in public domain. We believe this will help subscribers identify strategies employing Martingale techniques, as discussed in this previous post.

Disclaimer before we go any further with this : We are the owners of TickPrime SP500.

Here are the results of this code:

Here is the C2Explorer code for your perusal:

// Select Systems we want in charts
Int64[] systemsIds = { 90325773, 46106678, 97642708, 95943912, 92728998
                       , 89240089, 94739988, 96506348, 93171889, 93192881
                     , 94661371, 97468745, 83833839, 75421760, 94514120
                     };
// Set starting date (YYYY,MM,DD)
var startingDate = new DateTime(2015,01,01);
// Create chart objects
ITimeSeriesChart notionalValueChart = new TimeSeriesChart();
notionalValueChart.Name = "Notional Value";
ITimeSeriesChart leverageMultipleChart = new TimeSeriesChart();
leverageMultipleChart.Name = "Leverage Multiple";
// Variables
Random random = new Random();
decimal netOpenPos = 0;
List<ITimeSeriesPoint> nvData = new List<ITimeSeriesPoint>();
List<ITimeSeriesPoint> lmData = new List<ITimeSeriesPoint>();
List<ITimeSeriesPoint> npData = new List<ITimeSeriesPoint>();
// Add Systems to charts
foreach (var id in systemsIds)
{
    // Initialize Charts data for System
    IChartTimeSeries nvChSeries = new ChartTimeSeries();
    nvChSeries.Type = ChartTypes.Line;
    nvChSeries.Name = (from sys in C2SYSTEMS where sys.SystemId == id select sys.SystemName).First();
    nvChSeries.Color = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));
    IChartTimeSeries lmChSeries = new ChartTimeSeries();
    lmChSeries.Type = ChartTypes.Line;
    lmChSeries.Name = nvChSeries.Name;
    lmChSeries.Color = nvChSeries.Color;
    // Reset Variables for System
    netOpenPos = 0;
    nvData = new List<ITimeSeriesPoint>();
    lmData = new List<ITimeSeriesPoint>();
    // Identify Positions and NotionalValue
    foreach (var sigQ in (from sig in C2SIGNALS 
                        where (sig.SystemId == id && sig.TradedWhen > startingDate)
                        orderby sig.Id 
                        select new 
                        {d=sig.TradedWhen,q=sig.Quant,a=sig.Action,p=sig.TradePrice,ptV=sig.PtValue}
                       ))
    {
      if(sigQ.a == "BTO" || sigQ.a == "BTC"){ netOpenPos += sigQ.q; }else if(sigQ.a == "STO" || sigQ.a == "STC"){ netOpenPos -= sigQ.q; }
      nvData.Add( new TimeSeriesPoint() { DateTime = sigQ.d, Value = (double)(sigQ.ptV*sigQ.p*netOpenPos) });
    }
    // Identify Leverage
    foreach (var nv in nvData)
    {
      var eqPtVal = (from eqdata in C2EQUITY where (eqdata.SystemId == id && eqdata.DateTime > nv.DateTime) orderby eqdata.DateTime ascending select eqdata.Value).First();
      lmData.Add(new TimeSeriesPoint() { DateTime = nv.DateTime, Value = Math.Abs(nv.Value/(double)eqPtVal) });
    }
    // Configure Charts
    nvChSeries.Data = nvData;
    notionalValueChart.Add(nvChSeries);
    lmChSeries.Data = lmData;
    leverageMultipleChart.Add(lmChSeries);
}
// Plot the Charts
CHART = leverageMultipleChart;
HR();
CHART = notionalValueChart;

Finally, it will be nice if you can share any modifications to this code, which you believe will benefit others.

Regards,
ACA

6 Likes

This is fantastic thank you. It would be really great if C2 could incorporate it into the design of every system page.

1 Like

When I use this code in Explorer I get this error message:
7:43:51 PM: *** Error: Sequence contains no elements

Dear TrendNeutral,

We are no longer active on C2.

The error you received occurs if the C2 strategies you chose do not have all the data fields for the time period. You can try changing the starting period or the strategies to narrow down on what is causing the error.

Hope C2 helpdesk can help you further in this matter. Good luck!

Regards,
ACA

This is an extremely insightful post and thanks for the code!

I ran the code on a system that trades currencies and it showed somehow surprising results.

One of the problems is probably in this line:

nvData.Add( new TimeSeriesPoint() { DateTime = sigQ.d, Value = (double)(sigQ.ptVsigQ.pnetOpenPos) });

Problem is that ptV for a currency pair XXXYYY is given in YYY.

I am digging some more but you are obviously much more experienced with this platform than I am (this is my first day!), so I give you a headsup, maybe this is something you have the time to fix.

Thanks again!

Joseph

I see that the OP is no longer active so I tweaked the code a bit.

Now it works for FOREX systems, by calculating the UNLEVEREGED margin as it is given by C2: number of contracts * size (10,000) * exchange rate.

For exchange rate I added the current exchange rates – so it is not “guite” accurate for historical prices. Sue me!

Also, IMHO there was a conceptual bug in the original code: it adde to the “nominal value” when a position was bought (regardless whether it was BTO or BTC) and subtracted when it was sold. This is not correct (I changed it) as the margin increases when we open a position (regardless of the direction) and decreases when we close it.

The “nominal value” graph now shows the unlevereged value of the account. Of course at Forex one can trade with 50 or more leverage; this is just fyi. You decide how to treat the raw data.

The code is below.

Enjoy,

Joseph

// Select FOREX Systems we want in charts.
// NOT generalized yet to trade any system.
Int64 systemsIds = { 94987184, // Just forex
101623769 // Athena Triumph
// 83803243 // Zip4x
};

// Set starting date (YYYY,MM,DD)
var startingDate = new DateTime(2015,01,01);

// Dictionary for currency → USD multiplier
var MultiplierByName = new Dictionary<string, double>()
{
{“USD”,1.0},
{“AUD”, 0.7493},
{“CAD”, 0.7569},
{“CHF”, 1.02},
{“EUR”, 1.1158},
{“GBP”, 1.3},
{“JPY”, 0.009777},
{“NZD”, 0.7265}
};

// Create chart objects
ITimeSeriesChart notionalValueChart = new TimeSeriesChart();
notionalValueChart.Name = “Total margin”;
ITimeSeriesChart leverageMultipleChart = new TimeSeriesChart();
leverageMultipleChart.Name = “Leverage Multiple”;

// Variables
Random random = new Random();
decimal netOpenPos = 0;
List nvData = new List();
List lmData = new List();
List npData = new List();

// Add Systems to charts
foreach (var id in systemsIds)
{
// Initialize Charts data for System
IChartTimeSeries nvChSeries = new ChartTimeSeries();
nvChSeries.Type = ChartTypes.Line;
nvChSeries.Name = (from sys in C2SYSTEMS where sys.SystemId == id select sys.SystemName).First();
nvChSeries.Color = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));

IChartTimeSeries lmChSeries = new ChartTimeSeries();
lmChSeries.Type = ChartTypes.Line;
lmChSeries.Name = nvChSeries.Name;
lmChSeries.Color = nvChSeries.Color;
// Reset Variables for System
// netOpenPos = 0;
// netValue is the total we need in margin. So when we open a position, increases.
double netValue = 0.0;
nvData = new List<ITimeSeriesPoint>();
lmData = new List<ITimeSeriesPoint>();
// Identify Positions and NotionalValue
foreach (var sigQ in (from sig in C2SIGNALS 
                    where (sig.SystemId == id && sig.TradedWhen > startingDate)
                    orderby sig.TradedWhen ascending
                    select new 
                    {mplier=sig.Currency,d=sig.TradedWhen,q=sig.Quant,a=sig.Action,p=sig.TradePrice,ptV=sig.PtValue}
                   ))
{
  // The price is NOT part of the tradeValue. For FOREX the trade is measured
  // by the quantity * pointValue of the second member of the pair.
  double tradeValue = (double)(sigQ.q * sigQ.p * sigQ.ptV);
  tradeValue *= MultiplierByName[sigQ.mplier];
  // tradevalus is $25K of quantity

// double tradeValue = (double)sigQ.q * 25000.0;
// For opening trade (regardless of direction) our margin increases,
// for closing trade it is decreases.
if(sigQ.a == “BTO” || sigQ.a == “STO”)
{ netValue += (double)tradeValue; }
else if(sigQ.a == “BTC” || sigQ.a == “STC”)
{ netValue -= (double)tradeValue; }
nvData.Add( new TimeSeriesPoint() { DateTime = sigQ.d, Value = netValue });
}

// Identify Leverage
foreach (var nv in nvData)
{
  var eqPtVal = (from eqdata in C2EQUITY where (eqdata.SystemId == id && eqdata.DateTime > nv.DateTime) orderby eqdata.DateTime ascending select eqdata.Value).First();
  lmData.Add(new TimeSeriesPoint() { DateTime = nv.DateTime, Value = Math.Abs(nv.Value/(double)eqPtVal) });
}
// Configure Charts
nvChSeries.Data = nvData;
notionalValueChart.Add(nvChSeries);
lmChSeries.Data = lmData;
leverageMultipleChart.Add(lmChSeries);

}

// Plot the Charts
CHART = notionalValueChart;
HR();
CHART = leverageMultipleChart;

1 Like

I tried this code and changed some syntaxe quirks to be able to compile it and run.
(Apparently we changed something in the server and the old code did not compile.)

It runs fine now.

Thanks Jozsika!

// https://forums.collective2.com/t/measuring-leverage/8394/6
// Select FOREX Systems we want in charts.
// NOT generalized yet to trade any system.
Int64[] systemsIds = { 94987184, // Just forex
 101623769 // Athena Triumph
 // 83803243 // Zip4x
 };

// Set starting date (YYYY,MM,DD)
var startingDate = new DateTime(2015,01,01);

// Dictionary for currency -> USD multiplier
var MultiplierByName = new Dictionary<string,double>() 
{ 
 {"USD",1.0},
 {"AUD", 0.7493},
 {"CAD", 0.7569},
 {"CHF", 1.02},
 {"EUR", 1.1158},
 {"GBP", 1.3},
 {"JPY", 0.009777},
 {"NZD", 0.7265}
};

// Create chart objects
ITimeSeriesChart notionalValueChart = new TimeSeriesChart();
notionalValueChart.Name = "Total margin";
ITimeSeriesChart leverageMultipleChart = new TimeSeriesChart();
leverageMultipleChart.Name = "Leverage Multiple";

// Variables
Random random = new Random();
decimal netOpenPos = 0;
var nvData = new List<ITimeSeriesPoint>();
var lmData = new List<ITimeSeriesPoint>();
var npData = new List<ITimeSeriesPoint>();

// Add Systems to charts
foreach (var id in systemsIds)
{
 // Initialize Charts data for System
 IChartTimeSeries nvChSeries = new ChartTimeSeries();
 nvChSeries.Type = ChartTypes.Line;
 nvChSeries.Name = (from sys in C2SYSTEMS where sys.SystemId == id select sys.SystemName).First();
 nvChSeries.Color = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));
IChartTimeSeries lmChSeries = new ChartTimeSeries();
lmChSeries.Type = ChartTypes.Line;
lmChSeries.Name = nvChSeries.Name;
lmChSeries.Color = nvChSeries.Color;

// Reset Variables for System
// netOpenPos = 0;
// netValue is the total we need in margin. So when we open a position, increases.
double netValue = 0.0;
nvData = new List<ITimeSeriesPoint>();
lmData = new List<ITimeSeriesPoint>();

// Identify Positions and NotionalValue
foreach (var sigQ in (from sig in C2SIGNALS 
                    where (sig.SystemId == id && sig.TradedWhen > startingDate)
                    orderby sig.TradedWhen ascending
                    select new 
                    {mplier=sig.Currency,d=sig.TradedWhen,q=sig.Quant,a=sig.Action,p=sig.TradePrice,ptV=sig.PtValue}
                   ))
{
  // The price is NOT part of the tradeValue. For FOREX the trade is measured
  // by the quantity * pointValue of the second member of the pair.
  double tradeValue = (double)(sigQ.q * sigQ.p * sigQ.ptV);
  tradeValue *= MultiplierByName[sigQ.mplier];
	// tradevalus is $25K of quantity

// double tradeValue = (double)sigQ.q * 25000.0;
 // For opening trade (regardless of direction) our margin increases,
 // for closing trade it is decreases.
 if(sigQ.a == "BTO" || sigQ.a == "STO") 
 { netValue += (double)tradeValue; }
 else if(sigQ.a == "BTC" || sigQ.a == "STC")
 { netValue -= (double)tradeValue; }
 nvData.Add( new TimeSeriesPoint() { DateTime = sigQ.d, Value = netValue });
 }
// Identify Leverage
foreach (var nv in nvData)
{
  var eqPtVal = (from eqdata in C2EQUITY where (eqdata.SystemId == id && eqdata.DateTime > nv.DateTime) orderby eqdata.DateTime ascending select eqdata.Value).First();
  lmData.Add(new TimeSeriesPoint() { DateTime = nv.DateTime, Value = Math.Abs(nv.Value/(double)eqPtVal) });
}

// Configure Charts
nvChSeries.Data = nvData;
notionalValueChart.Add(nvChSeries);
lmChSeries.Data = lmData;
leverageMultipleChart.Add(lmChSeries);

}

// Plot the Charts
CHART = notionalValueChart;
HR();
CHART = leverageMultipleChart;

1 Like

I modified the multipliers using IB’s leveraged forex margins so that the total margin and leverage multiple make sense for leveraged accounts. Thanks Joseph and Bob!

// https://forums.collective2.com/t/measuring-leverage/8394/6
// Select FOREX Systems we want in charts.
// NOT generalized yet to trade any system.
// Uses IB margins
Int64[] systemsIds = { 101623769 // Athena Triumph
 // 83803243 // Zip4x
 };

// Set starting date (YYYY,MM,DD)
var startingDate = new DateTime(2015,01,01);

// Dictionary for currency -> USD multiplier
var MultiplierByName = new Dictionary<string,double>() 
{ 
 {"USD",1.0*.025},
 {"AUD", 0.7493*.03},
 {"CAD", 0.7569*.025},
 {"CHF", 1.02*.04},
 {"EUR", 1.1158*.03},
 {"GBP", 1.3*.05},
 {"JPY", 0.009777*.03},
 {"NZD", 0.7265*.0333}
};

// Create chart objects
ITimeSeriesChart notionalValueChart = new TimeSeriesChart();
notionalValueChart.Name = "Total margin";
ITimeSeriesChart leverageMultipleChart = new TimeSeriesChart();
leverageMultipleChart.Name = "Leverage Multiple";

// Variables
Random random = new Random();
decimal netOpenPos = 0;
var nvData = new List<ITimeSeriesPoint>();
var lmData = new List<ITimeSeriesPoint>();
var npData = new List<ITimeSeriesPoint>();

// Add Systems to charts
foreach (var id in systemsIds)
{
 // Initialize Charts data for System
 IChartTimeSeries nvChSeries = new ChartTimeSeries();
 nvChSeries.Type = ChartTypes.Line;
 nvChSeries.Name = (from sys in C2SYSTEMS where sys.SystemId == id select sys.SystemName).First();
 nvChSeries.Color = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));
IChartTimeSeries lmChSeries = new ChartTimeSeries();
lmChSeries.Type = ChartTypes.Line;
lmChSeries.Name = nvChSeries.Name;
lmChSeries.Color = nvChSeries.Color;

// Reset Variables for System
// netOpenPos = 0;
// netValue is the total we need in margin. So when we open a position, increases.
double netValue = 0.0;
nvData = new List<ITimeSeriesPoint>();
lmData = new List<ITimeSeriesPoint>();

// Identify Positions and NotionalValue
foreach (var sigQ in (from sig in C2SIGNALS 
                    where (sig.SystemId == id && sig.TradedWhen > startingDate)
                    orderby sig.TradedWhen ascending
                    select new 
                    {mplier=sig.Currency,d=sig.TradedWhen,q=sig.Quant,a=sig.Action,p=sig.TradePrice,ptV=sig.PtValue}
                   ))
{
  // The price is NOT part of the tradeValue. For FOREX the trade is measured
  // by the quantity * pointValue of the second member of the pair.
  double tradeValue = (double)(sigQ.q * sigQ.p * sigQ.ptV);
  tradeValue *= MultiplierByName[sigQ.mplier];
	// tradevalus is $25K of quantity

// double tradeValue = (double)sigQ.q * 25000.0;
 // For opening trade (regardless of direction) our margin increases,
 // for closing trade it is decreases.
 if(sigQ.a == "BTO" || sigQ.a == "STO") 
 { netValue += (double)tradeValue; }
 else if(sigQ.a == "BTC" || sigQ.a == "STC")
 { netValue -= (double)tradeValue; }
 nvData.Add( new TimeSeriesPoint() { DateTime = sigQ.d, Value = netValue });
 }
// Identify Leverage
foreach (var nv in nvData)
{
  var eqPtVal = (from eqdata in C2EQUITY where (eqdata.SystemId == id && eqdata.DateTime > nv.DateTime) orderby eqdata.DateTime ascending select eqdata.Value).First();
  lmData.Add(new TimeSeriesPoint() { DateTime = nv.DateTime, Value = Math.Abs(nv.Value/(double)eqPtVal) });
}

// Configure Charts
nvChSeries.Data = nvData;
notionalValueChart.Add(nvChSeries);
lmChSeries.Data = lmData;
leverageMultipleChart.Add(lmChSeries);

}

// Plot the Charts
CHART = notionalValueChart;
HR();
CHART = leverageMultipleChart;
1 Like