Skip to content

Commit

Permalink
Major changes to Order Entry, Option/Futures Assignment, Reconciliati…
Browse files Browse the repository at this point in the history
…on, and GUI elements. May possibly affect quantiry values of some transactions already entered in your database.
  • Loading branch information
PaulSquires committed Aug 18, 2023
1 parent b9d11ea commit af5d45d
Show file tree
Hide file tree
Showing 20 changed files with 191 additions and 129 deletions.
57 changes: 40 additions & 17 deletions IB-Tracker/src/ActiveTrades/ActiveTrades.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,18 @@ void ActiveTrades_ShowActiveTrades()

// Create the new ListBox line data and initiate the new market data.
int categoryHeader = -1;
for (const auto& trade : trades) {
for (auto& trade : trades) {
// We are displaying only open trades
if (trade->isOpen) {
// Set the decimals for this tickerSymbol. Most will be 2 but futures can have a lot more.
trade->tickerDecimals = GetTickerDecimals(trade->tickerSymbol);

if (trade->category != categoryHeader) {
ListBoxData_AddCategoryHeader(hListBox, trade);
categoryHeader = trade->category;
}
ListBoxData_OpenPosition(hListBox, trade, tickerId);

// Set the decimals for this tickerSymbol. Most will be 2 but futures can have a lot more.
trade->tickerDecimals = GetTickerDecimals(trade->tickerSymbol);

tickerId++;
if (tickerId > 500) tickerId = 100;
}
Expand Down Expand Up @@ -208,6 +208,8 @@ void ActiveTrades_ShowActiveTrades()
ListBox_SetSel(hListBox, true, curSel);
ActiveTrades_ShowListBoxItem(curSel);

RECT rc; GetClientRect(HWND_ACTIVETRADES, &rc);
ActiveTrades_OnSize(HWND_ACTIVETRADES, 0, rc.right, rc.bottom);

SetFocus(hListBox);

Expand Down Expand Up @@ -361,22 +363,25 @@ void ActiveTrades_CalledAwayAssignment(
std::shared_ptr<Transaction> trans;
std::shared_ptr<Leg> newleg;

bool isShares = (trade->tickerSymbol.substr(0, 1) == L"/") ? false : true;
bool isShares = (IsFuturesTicker(trade->tickerSymbol)) ? false : true;

int QuantityAssigned = 0;
int NumLegQuantity = 0;
double multiplier = 1;

std::wstring msg = L"Continue with OPTION ASSIGNMENT?\n\n";

if (isShares == true) {
QuantityAssigned = min(abs(leg->openQuantity * 100), abs(NumSharesAggregate));
NumLegQuantity = QuantityAssigned / 100;
msg += std::to_wstring(QuantityAssigned) + L" shares called away at $" + leg->strikePrice + L" per share.";
multiplier = 1;
}
else {
QuantityAssigned = min(abs(leg->openQuantity), abs(NumFuturesAggregate));
NumLegQuantity = QuantityAssigned;
msg += std::to_wstring(QuantityAssigned) + L" futures called away at $" + leg->strikePrice + L" per future.";
multiplier = trade->multiplier;
}
NumLegQuantity = (leg->openQuantity < 0) ? NumLegQuantity * -1 : NumLegQuantity;

Expand Down Expand Up @@ -420,8 +425,8 @@ void ActiveTrades_CalledAwayAssignment(
trans->description = L"Called away";
trans->underlying = (isShares == true) ? L"SHARES" : L"FUTURES";
trans->quantity = QuantityAssigned;
trans->price = stod(leg->strikePrice);
trans->multiplier = 1;
trans->price = AfxValDouble(leg->strikePrice);
trans->multiplier = multiplier;
trans->fees = 0;
trade->Transactions.push_back(trans);

Expand All @@ -435,14 +440,14 @@ void ActiveTrades_CalledAwayAssignment(
newleg->action = L"BTC";
newleg->origQuantity = QuantityAssigned;
newleg->openQuantity = QuantityAssigned;
trans->total = trans->quantity * trans->price * -1; // DR
trans->total = trans->quantity * multiplier * trans->price * -1; // DR
trade->ACB = trade->ACB + trans->total;
}
else {
newleg->action = L"STC";
newleg->origQuantity = QuantityAssigned * -1;
newleg->openQuantity = QuantityAssigned * -1;
trans->total = trans->quantity * trans->price; // CR
trans->total = trans->quantity * multiplier * trans->price; // CR
trade->ACB = trade->ACB + trans->total;
}

Expand Down Expand Up @@ -477,16 +482,19 @@ void ActiveTrades_Assignment(auto trade, auto leg)
bool isShares = (trade->tickerSymbol.substr(0,1) == L"/") ? false : true;

int QuantityAssigned = 0;
double multiplier = 1;

std::wstring wszLongShort = (leg->PutCall == L"P") ? L"LONG " : L"SHORT ";
std::wstring msg = L"Continue with OPTION ASSIGNMENT?\n\n";

if (isShares == true) {
QuantityAssigned = abs(leg->openQuantity * 100);
multiplier = 1;
msg += wszLongShort + std::to_wstring(QuantityAssigned) + L" shares at $" + leg->strikePrice + L" per share.";
}
else {
QuantityAssigned = abs(leg->openQuantity);
multiplier = trade->multiplier;
msg += wszLongShort + std::to_wstring(QuantityAssigned) + L" futures at $" + leg->strikePrice + L" per future.";
}

Expand Down Expand Up @@ -530,8 +538,8 @@ void ActiveTrades_Assignment(auto trade, auto leg)
trans->description = L"Assignment";
trans->underlying = (isShares == true) ? L"SHARES" : L"FUTURES";
trans->quantity = QuantityAssigned;
trans->price = stod(leg->strikePrice);
trans->multiplier = 1;
trans->price = AfxValDouble(leg->strikePrice);
trans->multiplier = multiplier;
trans->fees = 0;
trade->Transactions.push_back(trans);

Expand All @@ -545,14 +553,14 @@ void ActiveTrades_Assignment(auto trade, auto leg)
newleg->action = L"BTO";
newleg->origQuantity = QuantityAssigned;
newleg->openQuantity = QuantityAssigned;
trans->total = trans->quantity * trans->price * -1; // DR
trans->total = trans->quantity * multiplier * trans->price * -1; // DR
trade->ACB = trade->ACB + trans->total;
}
else {
newleg->action = L"STO";
newleg->origQuantity = QuantityAssigned * -1;
newleg->openQuantity = QuantityAssigned * -1;
trans->total = trans->quantity * trans->price; // CR
trans->total = trans->quantity * multiplier * trans->price; // CR
trade->ACB = trade->ACB + trans->total;
}

Expand Down Expand Up @@ -673,10 +681,16 @@ void ActiveTrades_RightClickMenu(HWND hListBox, int idx)

bool IsTickerLine = false;

// Clear the tdd module global trade variable
tdd.ResetDefaults();

int nCurSel = ListBox_GetCurSel(hListBox);
ListBoxData* ld = (ListBoxData*)ListBox_GetItemData(hListBox, nCurSel);
if (ld->trade == nullptr) return;

trade = ld->trade;
tdd.trade = ld->trade;
tdd.trans = ld->trans;
tdd.sharesAggregateEdit = ld->AggregateShares;

if (nCount == 1) {
Expand Down Expand Up @@ -726,8 +740,12 @@ void ActiveTrades_RightClickMenu(HWND hListBox, int idx)
InsertMenu(hMenu, 0, MF_BYCOMMAND | MF_STRING | MF_ENABLED, (int)TradeAction::AddPutToTrade, L"Add Put to Trade");
InsertMenu(hMenu, 0, MF_BYCOMMAND | MF_STRING | MF_ENABLED, (int)TradeAction::AddCallToTrade, L"Add Call to Trade");
InsertMenu(hMenu, 0, MF_BYCOMMAND | MF_SEPARATOR | MF_ENABLED, (int)TradeAction::NoAction + 3, L"");
InsertMenu(hMenu, 0, MF_BYCOMMAND | MF_STRING | MF_ENABLED, (int)TradeAction::AddSharesToTrade, L"Add Shares to Trade");
InsertMenu(hMenu, 0, MF_BYCOMMAND | MF_STRING | MF_ENABLED, (int)TradeAction::AddFuturesToTrade, L"Add Futures to Trade");

if (IsFuturesTicker(trade->tickerSymbol)) {
InsertMenu(hMenu, 0, MF_BYCOMMAND | MF_STRING | MF_ENABLED, (int)TradeAction::AddFuturesToTrade, L"Add Futures to Trade");
} else {
InsertMenu(hMenu, 0, MF_BYCOMMAND | MF_STRING | MF_ENABLED, (int)TradeAction::AddSharesToTrade, L"Add Shares to Trade");
}

POINT pt; GetCursorPos(&pt);
TradeAction selected =
Expand Down Expand Up @@ -959,6 +977,9 @@ void ActiveTrades_OnSize(HWND hwnd, UINT state, int cx, int cy)

int margin = AfxScaleY(ACTIVETRADES_MARGIN);

// If no entries exist for the ListBox then don't show any child controls
int showflag = (ListBox_GetCount(hListBox) <= 1) ? SWP_HIDEWINDOW : SWP_SHOWWINDOW;

HDWP hdwp = BeginDeferWindowPos(5);

// Move and size the top label into place
Expand All @@ -985,12 +1006,14 @@ void ActiveTrades_OnSize(HWND hwnd, UINT state, int cx, int cy)
int nTop = margin;
int nHeight = cy - nTop;
int nWidth = cx - CustomVScrollBarWidth;
hdwp = DeferWindowPos(hdwp, hListBox, 0, nLeft, nTop, nWidth, nHeight, SWP_NOZORDER | SWP_SHOWWINDOW);
hdwp = DeferWindowPos(hdwp, hListBox, 0, nLeft, nTop, nWidth, nHeight, SWP_NOZORDER | showflag);

nLeft = nLeft + nWidth; // right edge of ListBox
nWidth = CustomVScrollBarWidth;
int showscrollbar = (bShowScrollBar ? SWP_SHOWWINDOW : SWP_HIDEWINDOW);
if (showflag == SWP_HIDEWINDOW) showscrollbar = SWP_HIDEWINDOW;
hdwp = DeferWindowPos(hdwp, hCustomVScrollBar, 0, nLeft, nTop, nWidth, nHeight,
SWP_NOZORDER | (bShowScrollBar ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
SWP_NOZORDER | showflag);

EndDeferWindowPos(hdwp);
}
Expand Down
16 changes: 15 additions & 1 deletion IB-Tracker/src/Config/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,24 @@ std::unordered_map<std::wstring, std::wstring> mapMultipliers {
};

std::unordered_map<std::wstring, int> mapTickerDecimals {
{ L"/AUD", 5 }
{ L"/AUD", 5 },
{ L"/ZB", 3 },
{ L"/ZC", 3 },
{ L"/ZS", 4 }
};



// ========================================================================================
// Determine if the incoming ticker symbol is a Future.
// ========================================================================================
bool IsFuturesTicker(const std::wstring& wszTicker)
{
return (wszTicker.substr(0, 1) == L"/");
}



// ========================================================================================
// Get the Ticker Decimals for the incoming underlying.
// ========================================================================================
Expand Down
3 changes: 2 additions & 1 deletion IB-Tracker/src/Config/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ SOFTWARE.

#pragma once

constexpr std::wstring version = L"1.2.1";
constexpr std::wstring version = L"2.0.0";

bool SaveConfig();
bool LoadConfig();
Expand All @@ -41,3 +41,4 @@ std::wstring GetCategoryDescription(int idxCategory);
void SetCategoryDescription(int idxCategory, std::wstring wszDescription);
bool GetStartupConnect();
void SetStartupConnect(bool bConnect);
bool IsFuturesTicker(const std::wstring& wszTicker);
1 change: 1 addition & 0 deletions IB-Tracker/src/CustomTextBox/CustomTextBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ std::wstring CustomTextBox_GetUserData(HWND hCtrl)
if (pData != nullptr) {
return pData->UserData;
}
return L"";
}


Expand Down
2 changes: 1 addition & 1 deletion IB-Tracker/src/Database/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ bool LoadDatabase()
leg->action = NumberToAction(try_catch_int(st, 8));
leg->underlying = NumberToUnderlying(try_catch_int(st, 9));
if (trans != nullptr) {
leg->trans = trans;
if (trade != nullptr) {
// Determine latest date for BP ROI calculation.
if (AfxValDouble(wszExpiryDate) > AfxValDouble(trade->BPendDate)) trade->BPendDate = wszExpiryDate;
Expand Down Expand Up @@ -317,7 +318,6 @@ bool LoadDatabase()
trade->ACB = 0;
for (const auto trans : trade->Transactions) {
trade->ACB = trade->ACB + trans->total;
trade->multiplier = trans->multiplier;
}
}

Expand Down
4 changes: 3 additions & 1 deletion IB-Tracker/src/Database/trade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ void Trade::createOpenLegsVector()
openLegs.clear();

for (const auto &trans : Transactions) {
for (const auto &leg : trans->legs) {
if (trans->multiplier > 0) this->multiplier = trans->multiplier;
for (auto &leg : trans->legs) {
if (leg->isOpen()) {
leg->trans = trans;
openLegs.push_back(leg);
}
}
Expand Down
7 changes: 5 additions & 2 deletions IB-Tracker/src/Database/trade.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ SOFTWARE.
//


class Transaction; // forward declare


class Leg
{
Expand All @@ -51,6 +53,7 @@ class Leg
std::wstring action = L""; // STO,BTO,STC,BTC
std::wstring underlying = L""; // OPTIONS, STOCKS, FUTURES
bool isOpen(); // method to calc if leg quantity is not zero
std::shared_ptr<Transaction> trans = nullptr; // back pointer to transaction that this leg belongs to
};


Expand Down Expand Up @@ -83,7 +86,7 @@ class Trade
double ACB = 0;
double TradeBP = 0; // Buying Power for the entire trade
int nextLegID = 0; // Incrementing counter that gets unique ID for legs being generated in TransDetail.
double multiplier = 0; // Updated from Transaction and needed for updatePortfolio real time calculations
double multiplier = 0; // Retrieved from Transaction and needed for updatePortfolio real time calculations

double tickerLastPrice = 0;
double tickerClosePrice = 0;
Expand All @@ -95,7 +98,7 @@ class Trade
std::wstring OldestTradeTransDate = L"00000000"; // If Trade is closed then this trans will be the BPendDate


std::vector<std::shared_ptr<Transaction>> Transactions; // pointer list for all TransDetail in the trade
std::vector<std::shared_ptr<Transaction>> Transactions; // pointer list for all transactions in the trade
std::vector<std::shared_ptr<Leg>> openLegs; // sorted list of open legs for this trade

void setTradeOpenStatus();
Expand Down
15 changes: 0 additions & 15 deletions IB-Tracker/src/MainWindow/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,21 +498,6 @@ LRESULT CMainWindow::HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam)
return 0;
}


case MSG_CATEGORY_CHANGED:
{
if (HWND_MIDDLEPANEL == ActiveTrades.WindowHandle()) {
// Destroy any existing ListBox line data
// This will also clear the LineData pointers and cancel any previous market data
ListBoxData_DestroyItemData(GetDlgItem(ActiveTrades.WindowHandle(), IDC_TRADES_LISTBOX));
ActiveTrades_ShowActiveTrades();
}
if (HWND_MIDDLEPANEL == TransPanel.WindowHandle()) {
TransPanel_ShowTransactions();
}
return 0;
}

default: return DefWindowProc(m_hwnd, msg, wParam, lParam);
}
}
Expand Down
9 changes: 5 additions & 4 deletions IB-Tracker/src/MainWindow/tws-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ void tws_performReconciliation()
// The results have been loaded into module global resultsText which will be displayed
// when Reconcile_Show() is called and Reconcile_positionEnd() has SendMessage notification
// to the dialog to say that text is ready.
tws_requestPortfolioUpdates();
// Load the IBKR and Local positions into the vectors and do the matching
client.cancelPositions();
client.requestPositions();

// Show the results
Reconcile_Show();
Expand Down Expand Up @@ -487,14 +489,14 @@ void TwsClient::tickPrice(TickerId tickerId, TickType field, double price, const
for (const auto& leg : ld->trade->openLegs) {
if (leg->underlying == L"OPTIONS") {
if (leg->PutCall == L"P") {
if (ld->trade->tickerLastPrice < std::stod(leg->strikePrice)) {
if (ld->trade->tickerLastPrice < AfxValDouble(leg->strikePrice)) {
leg->openQuantity < 0 ? isITMred = true : isITMred = false;
leg->openQuantity > 0 ? isITMgreen = true : isITMgreen = false;
break;
}
}
else if (leg->PutCall == L"C") {
if (ld->trade->tickerLastPrice > std::stod(leg->strikePrice)) {
if (ld->trade->tickerLastPrice > AfxValDouble(leg->strikePrice)) {
leg->openQuantity < 0 ? isITMred = true : isITMred = false;
leg->openQuantity > 0 ? isITMgreen = true : isITMgreen = false;
break;
Expand Down Expand Up @@ -560,7 +562,6 @@ void TwsClient::updatePortfolio(const Contract& contract, Decimal position,
// Utils::doubleMaxString(marketPrice).c_str(), Utils::doubleMaxString(marketValue).c_str(), Utils::doubleMaxString(averageCost).c_str(),
// Utils::doubleMaxString(unrealizedPNL).c_str(), Utils::doubleMaxString(realizedPNL).c_str(), accountName.c_str());


// Match the incoming contractID with the contractId stored in the Leg.

HWND hListBox = GetDlgItem(HWND_ACTIVETRADES, IDC_TRADES_LISTBOX);
Expand Down
6 changes: 3 additions & 3 deletions IB-Tracker/src/Reconcile/Reconcile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SOFTWARE.
#include "Database/trade.h"
#include "Utilities/IntelDecimal.h"
#include "Utilities/UserMessages.h"
#include "Config/Config.h"
#include "Reconcile.h"


Expand Down Expand Up @@ -115,12 +116,12 @@ void Reconcile_positionEnd()
if (leg->underlying == L"OPTIONS") p.underlying = L"OPT";
if (leg->underlying == L"SHARES") p.underlying = L"STK";

p.strikePrice = stod(leg->strikePrice);
p.strikePrice = AfxValDouble(leg->strikePrice);
p.expiryDate = AfxRemoveDateHyphens(leg->expiryDate);
p.PutCall = leg->PutCall;

// Check if the ticker is a future
if (p.tickerSymbol.substr(0, 1) == L"/") {
if (IsFuturesTicker(p.tickerSymbol)) {
p.tickerSymbol = trade->tickerSymbol.substr(1);
if (p.underlying == L"OPT") p.underlying = L"FOP";
}
Expand Down Expand Up @@ -164,7 +165,6 @@ void Reconcile_positionEnd()
}



// (1) Determine what IBKR "real" positions do not exist in the Local database.
ResultsText = L"IBKR that do not exist in Local:\r\n";
for (const auto& ibkr : IBKRPositions) {
Expand Down
Loading

0 comments on commit af5d45d

Please sign in to comment.