I have coded it in a different manner avoiding having to handle any of the
Interopt coding myself. I have VS 2008 Pro and the latest Windows SDK
installed. In VS, I just checked the project property on the Build tab to
"Register for COM Interop" and added a strong name key file on the "Signing"
tab. The strong name key file is used for installing the dll inthe GAC. You
can create this using the "sn.exe" application included in the WinSDK 6.1.
After writing my various classes, properties, and methods, I simply run the
following ".bat" script.
regasm /unregister ABTradingNetCS.dll > unregister.txt
regasm ABTradingNetCS.dll > register.txt
gacutil /u ABTradingNetCS > gacutil_remove.txt
gacutil /i ABTradingNetCS.dll > gacutil_add.txt
The gacutil.exe is also provided with the WinSDK 6.1. To make the path simple,
I just copied the regasm and gacutil applications to my build folder.
I use this COM lib to track order information, so I use a static object in
order to maintain state. With the COM componenets, you can only access one
level into the object, so you cannot in AFL do something like
Obj.SubObj.Property1 - instead you must get reference to SubObj to reference
Property1. Also, you cannot reference any static properties or methods from
AFL.
Here is a sample of the AFL code.
global xABT, xABBD, xABSD, xBD, xBDEOrder, xBDSLOrder, xBDTOrder, xSD,
xSDEOrder,
xSDSLOrder, xSDTOrder, xOH, xContract, xChartSymData;
function SetChartDataObjects()
{
xABT = CreateStaticObject("ABTradingNetCS.ABTrading");
xChartSymData = xABT.GetChartSymbolData(Name());
xContract = xABT.GetContract(Name());
xBD = xChartSymData.BuyOrderData;
xBDEOrder = xBD.OrderEntry;
xBDSLOrder = xBD.OrderStoploss;
xBDTOrder = xBD.OrderTarget;
xSD = xChartSymData.SellOrderData;
xSDEOrder = xSD.OrderEntry;
xSDSLOrder = xSD.OrderStoploss;
xSDTOrder = xSD.OrderTarget;
}
function TransmitOrders(orderSide)
{
local xOD, xOE, xOSL, xOT, xOC, doXmit, ibc ;
if ( ORderSide == 1 ) //buy side
{ xOD = xBD; xOE = xBDEOrder; xOSL = xBDSLOrder; xOT = xBDTOrder; }
else //sell side
{ xOD = xSD; xOE = xSDEOrder; xOSL = xSDSLOrder; xOT = xSDTOrder; }
ibc = GetTradingInterface( "IB" );
// check if we are connected OK
if (NOT xOD.OrderGroupSubmitted AND ibc.IsConnected() )
{
// check if we do not have already open position on this stock
if ( ibc.GetPositionSize( Name() ) == 0 )
{
xOD.OrderGroupSubmitted = True;
doXmit = False;
if ( NOT xOD.EnforceStopLossOrder AND NOT xOD.EnforceTargetOrder )
{
doXmit = True AND xOD.TransmitGroupToBroker;
}
// transmit order
xOE.OrderId = ibc.PlaceOrder(
xOE.Symbol,
xOE.Action, xOE.Quantity, xOE.Type, xOE.LimitPrice, xOE.StopPrice,
xOE.IBDateTime,
doXmit,
xOE.TickSize, xOE.Attributes);
if ( xOD.EnforceTargetOrder || xOT.PriceOfOrderEntry() > 0 )
{
if ( NOT xOD.EnforceStopLossOrder AND NOT xOSL.UseThisOrderPart
)
doXmit = True && xOD.TransmitGroupToBroker;
xOT.OrderId = ibc.PlaceOrder(
xOT.Symbol,
xOT.Action, xOT.Quantity, xOT.Type, xOT.LimitPrice, xOT.StopPrice,
xOT.IBDateTime,
doXmit,
xOT.TickSize, xOT.Attributes, xOE.OrderId, xOT.OcaGroup, xOT.OcaType );
}
if ( xOD.EnforceStopLossOrder || xOSL.PriceOfOrderEntry() > 0 )
{
doXmit = True && xOD.TransmitGroupToBroker;
xOSL.OrderId = ibc.PlaceOrder(
xOSL.Symbol,
xOSL.Action, xOSL.Quantity, xOSL.Type, xOSL.LimitPrice, xOSL.StopPrice,
xOSL.IBDateTime,
doXmit,
xOSL.TickSize, xOSL.Attributes, xOE.OrderId, xOSL.OcaGroup, xOSL.OcaType );
}
if ( xOD.AddCancelOrder )
{
xOC = xOD.OrderCancel;
xOC.OrderId = ibc.PlaceOrder(
xOC.Symbol,
xOC.Action, xOC.Quantity, xOC.Type, xOC.LimitPrice, xOC.StopPrice,
xOC.IBDateTime,
False,
xOC.TickSize, xOC.Attributes);
}
}
}
}
And here is some sample code for the C# for my contract data class. Most of
the code is removed to save space in the post.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class ABTradingContractData
{
private string _origSymbol; public string OrigSymbol { get { return
_origSymbol; } set { _origSymbol = value; } }
private string _orderSymbol; public string OrderSymbol { get { return
_orderSymbol; } set { _orderSymbol = value; } }
private string _exchange; public string Exchange { get { return
_exchange; } set { _exchange = value; } }
private string _currency; public string Currency { get { return
_currency; } set { _currency = value; } }
private string _type; public string Type { get { return _type; } set {
_type = value; } }
private string _currencyBase; public string CurrencyBase { get { return
_currencyBase; } set { _currencyBase = value; } }
private string _currencyCross; public string CurrencyCross { get {
return _currencyCross; } set { _currencyCross = value; } }
private double _decimalDisplay; public double DecimalDisplay { get {
return _decimalDisplay; } set { _decimalDisplay = value; } }
private bool _isForex = false; public bool IsForex { get { return
_isForex; } set { _isForex = value; } }
private bool _isFuture = false; public bool IsFuture { get { return
_isFuture; } set { _isFuture = value; } }
private double _tickSize = 0.01; public double TickSize { get { return
_tickSize; } set { _tickSize = value; } }
//forex values
private string _forexCurrencySymbol; public string ForexCurrencySymbol
{ get { return _forexCurrencySymbol; } set { _forexCurrencySymbol = value; } }
private double _minSize; public double MinSize { get { return _minSize;
} set { _minSize = value; } }
private string _currencySymbol = ""; public string CurrencySymbol { get
{ return _currencySymbol; } set { _currencySymbol = value; } }
private string _lotCurrency = ""; public string LotCurrency { get {
return _lotCurrency; } set { _lotCurrency = value; } }
private double _lotSize = 0; public double LotSize { get { return
_lotSize; } set { _lotSize = value; } }
private double _lotPipValue = 0; public double LotPipValue { get {
return _lotPipValue; } set { _lotPipValue = value; } }
private double _decimalFactor = 0; public double DecimalFactor { get {
return _decimalFactor; } set { _decimalFactor = value; } }
public ABTradingContractData(string symbol)
{
//code to initalize exchange, currency, security type, and order
symbol
}
public double GetFormattedPrice(double inputPrice )
{
double outputPrice = 0;
if ( inputPrice > 0 )
{
outputPrice = inputPrice;
if ( _isForex )
{
outputPrice = (double)((int)( inputPrice *
_decimalFactor )) / _decimalFactor ;
}
else
{
//format price for stock
outputPrice = (double)((int)( inputPrice * 100 )) /
100.0;
}
}
return outputPrice;
}
}
}
So if you don't like having to mess with GUIDs or Interopt Services, then here
is another way to approach using COM with AB. I have not tried it with the
manual interface with Interopt Services, but using the GAC method here, I can
actually step into the code and watch its excution in my VS project - although
edit and continue is not available.
Regards,
Tom