I am trying to create a program that helps me track all my day trading statistics. I have made an attempt at starting the project but after many days and much frustration, have decided to ask for some tips and help.
I have decided to take the approach of extracting the statistics from a text file and make the program do the calculations needed from the information in the text file. I don't know if this is the best approach or maybe it would be better to have the user input the information for each trade, that then writes it to a text file.
Here is the information I am looking for in my output;
Trades separated by bias; i.e. long & short:
All long trades listed from biggest win to smallest:
All short trades listed from biggest win to smallest:
Most Used Strategy:
Total $ Gains:
Total $ Losses
Total Number of Trades:
Average Winning Trade $ amount:
Average Losing Trade $ amount:
Number of Winning Trades:
Number of Losing Trades:
Largest $ Gain:
Largest $ Loss:
Winning Percentage:
Remaining capital:
This is what my text file looks like; (It only shows four trades as of now, I will add more once I get the program working)
October 2021
Starting Capital: $2500.00
trade 1
Strategy: FGD
bias: long
entryPrice:$3.25, exitPrice:$3.75, shares: 500
trade 2
Strategy: FRD
bias: short
entryPrice:$35.25, exitPrice:$34.75, shares: 100
trade 3
Strategy: AVH
bias: long
entryPrice:$15.25, exitPrice:$15.18, shares: 150
trade 4
Strategy: FRD
bias: short
entryPrice:$9.85, exitPrice:$9.92, shares: 300
This is coming from a text file from notepad. Is it possible to use an excel file instead?
Here is the code I have so far (not nearly complete). I am assuming its no where near correct and I am not even sure its going in the right direction. I have been studying D S Malik's book, "C++ Programming: Program Design Including Data Structures" for help but I'm still struggling with this project. If anyone could help me with this or give me tips, that would be highly appreciated.
// Trading Data Tracker.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
if (!infile)
{
cout << "Cannot open input file."
<< "Program is terminated." << endl;
return 1;
}
//Open output file
outfile.open("tradingData.out");
outfile << fixed << showpoint << setprecision(2);
{
infile>>num;
while (infile)
{
//code to sum the trading data
infile.get(ch);
getline(infile, strategy);
sum = 0;
infile >> num;
}
while (num != -999)
{
sum = sum - entryPrice * shares;
infile >> num;
}
I do have control of the format. I manually export my trades from my broker. Excel is what I prefer, I just am not sure how to export data from excel into C++.
I did not think of using the format you have shown. I am ok with doing it that way because it definitely would be easier to parse.
What would be the correct way to code it with this format?
Thanks for your input!
the correct way is what gets you the result you want.
this seems complicated enough to justify some simple OOP to organize the data and make it easier to deal with.
enum strategy{what, are, these};
struct trade
{
bool isLong{}; //long or short. you can also use an enum{long, short} or whatever here.
strategy Strat{};
unsignedint BuyPrice; //in cents
unsignedint SellPrice; //cents
some date type BuyDate; //you can use various ways to track date. a 64bit integer format YYYYMMDDHHMMSS will fit for example.
datetype SellDate; //as above
unsignedint numshares;
string serialize(); //return a formatted string of the fields with commas etc suitable for a cout or setwindowtext or whatever call.
};
struct symbol
{
string symbol; //name, "FRD" etc
vector<trade> trades;
///other fields as needed
string serialize(); //as above, format output. this one may need to compute things from <trades> like win/loss etc
}
then down in main you have
vector <symbol> mydata //or a map maybe? this seems like a good place for a map..
that you can load up, process, save, etc. you can sort by symbol name, filter by trade type (long/short), whatever here.
the key design component here is deciding what you will do in your program and what you will offload to excel (if anything). Unless you are using excel to draw charts, I would do all this in c++. But to me everything except graphing for this task seems easy in c++, if you are new to the language it may be easier to rig some of it into excel. IIRC you can write text formulae in csv and excel understands it, eg =sum(... type formula in a cell will work.. letting the c++ tell excel what to do
This is what I am trying to get the program to do:
Trades separated by bias; i.e. long & short:
All long trades listed from biggest win to smallest:
All short trades listed from biggest win to smallest:
Most Used Strategy:
Total $ Gains:
Total $ Losses
Total Number of Trades:
Average Winning Trade $ amount:
Average Losing Trade $ amount:
Number of Winning Trades:
Number of Losing Trades:
Largest $ Gain:
Largest $ Loss:
Winning Percentage:
Remaining capital:
I am new to C++ so I would be completely fine with having C++ do everything. I just wasn’t sure if that would be easier than reading from a file.
If I could code a program that gives me the above information all in c++ I would be happy with that start!
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
usingnamespace std;
struct Trade
{
string Symbol{};
bool isLong{}; //if true, then long, else short
int Strat{};
double BuyPrice{};
double SellPrice{};
int BuyDayOfMonth{}; // 1-31 .
int SellDayOfMonth{};
unsignedint numshares{};
double NetAmount{};
};
// Globals
int month;
int year;
double starting_capital;
vector<Trade> trades;
// Expected file format
// mm yyyy aaaaa.aa
// where mm is the month
// yyyy is the year
// aaaa.aa is the starting capital
// sym ls bd ba sd sa ns
// where sym is the stock symbol
// ls is 1 for long 0 for short
// st is integer representing strategy
// bd is the buy day of the month
// ba is the buy price per share
// sd is the sell day of the month
// sa is the sell price per share
// ns is the number of shares
//
bool read_csv_file()
{
ifstream is;
Trade temp;
is.open("trades.csv");
if (!is.is_open())
returnfalse; // File failed to open
// Read the header
is >> month;
is >> year;
is >> starting_capital;
// Read the trades
while (is >> temp.Symbol)
{
is >> temp.isLong;
is >> temp.Strat;
is >> temp.BuyDayOfMonth;
is >> temp.BuyPrice;
is >> temp.SellDayOfMonth;
is >> temp.SellPrice;
is >> temp.numshares;
temp.NetAmount = (temp.SellPrice - temp.BuyPrice) * temp.numshares;
trades.push_back (temp);
}
is.close(); // not needed; just being pedantic
returntrue;
}
// List one Trade (raw)
void ListTrade(const Trade& t)
{
cout << setw(5) << t.Symbol << " ";
cout << setw(2) << t.Strat << " ";
cout << setw(2) << t.BuyDayOfMonth << " ";
cout << setw(7) << t.BuyPrice << " ";
cout << setw(2) << t.SellDayOfMonth << " ";
cout << setw(7) << t.SellPrice << " ";
cout << setw(6) << t.numshares << " ";
cout << setw(6) << t.NetAmount;
cout << endl;
}
// List all trades that match the long or short argument
void ListRawTrades(bool ls)
{
if (ls)
cout << "All long trades" << endl;
else
cout << "All short trades" << endl;
cout << endl;
// ....+....2....+....3....+....4....+....5....+....6....+
// sssss st bd bbbbb.bb sd sssss.ss nnnnnn aaaaa.aa
cout << "Symbl ST BD BuyPrice SD SellPric Shares" << endl;
for (auto t : trades)
{
if (t.isLong == ls)
ListTrade(t); // List one matching trade
}
cout << endl;
}
// Calculate total gains and losses
void TotalGainsandLosses()
{
double total_gains = 0;
double total_losses = 0;
for (auto t : trades)
{
if (t.NetAmount > 0)
total_gains += t.NetAmount;
else
total_losses += t.NetAmount;
}
cout << "Total Gains = " << total_gains << endl;
cout << "Total Losses = " << total_losses << endl;
cout << endl;
}
int main()
{
if (!read_csv_file())
return 1;
// Sort vector biggest to smallest net amount
ListRawTrades(true); // List all long trades
ListRawTrades(false); // List all short trades
TotalGainsandLosses();
}
edit added after line 65:
trades.push_back (temp);
Edit #2: Fixed the >> in read_csv_file to be from is rather than cin.
@dwizz011
If @AbstractionAnon's work solves your problem then that's all to the well and good, possibly the end of the story. I have no comment to make about it or criticize it.
However it would be a good idea for you to also incorporate the advice from @Jonnin above. Not the code so much but the principles involved to avoid some pretty standard traps - particularly 'spaghetti code' that goes on and on forever in more and more convolutions of if's whiles and flags.
The key issue to consider surrounds the source of the data and what your final intended outcome is. If you already have the info on a personal spreadsheet (a database is better suited anyway) then why not stick with that. If it's a download from a stockbroker then why not stick with what the stockbroker has, a decent broker will have comprehensive reporting.
Downloading the data is only a snapshot, so why not just enter buy and sell trades to your program yourself. Entries can be timestamped with real times, and saved/retrieved from disk as required with updates as part of your program.
Probably a bit early in your programming career by the sound of it but struct's and classes towards an object-oriented approach is definitely the way to go.
The structs/classes could be Portfolio( <vectors>, reports), Transaction (Buy/Sell), Company (code, name) along with a menu and input.
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <map>
usingnamespace std;
//
// Objectives:
// * Trades separated by bias; i.e. long & short:
// * All long trades listed from biggest win to smallest :
// * All short trades listed from biggest win to smallest :
// * Most Used Strategy :
// * Total $ Gains :
// * Total $ Losses
// * Total Number of Trades :
// * Average Winning Trade $ amount :
// * Average Losing Trade $ amount :
// * Number of Winning Trades :
// * Number of Losing Trades :
// * Largest $ Gain :
// * Largest $ Loss :
// * Winning Percentage :
// * Remaining capital :
//
struct Trade
{
string Symbol{};
bool isLong{}; // 1 = long, 0 = short
int Strat{};
double BuyPrice{};
double SellPrice{};
int BuyDayOfMonth{}; // 1-31 .
int SellDayOfMonth{};
unsignedint numshares{};
// The following is calculated
double NetProfit{};
};
typedef map<int, int> strat_map_t;
// Globals
int month;
int year;
double starting_capital;
vector<Trade> trades;
// Expected file format
// mm yyyy aaaaa.aa
// where mm is the month
// yyyy is the year
// aaaa.aa is the starting capital
// sym ls bd ba sd sa ns
// where sym is the stock symbol
// ls is 1 for long 0 for short
// st is integer representing strategy
// bd is the buy day of the month
// ba is the buy price per share
// sd is the sell day of the month
// sa is the sell price per share
// ns is the number of shares
//
bool read_csv_file()
{
ifstream is;
Trade temp;
is.open("trades.csv");
if (!is.is_open())
returnfalse; // File failed to open
// Read the header
is >> month;
is >> year;
is >> starting_capital;
// Read the trades
while (is >> temp.Symbol)
{ is >> temp.isLong;
is >> temp.Strat;
is >> temp.BuyDayOfMonth;
is >> temp.BuyPrice;
is >> temp.SellDayOfMonth;
is >> temp.SellPrice;
is >> temp.numshares;
temp.NetProfit = (temp.SellPrice - temp.BuyPrice) * temp.numshares;
trades.push_back(temp);
}
is.close(); // not needed; just being pedantic
returntrue;
}
// List one Trade (raw)
void ListTrade(const Trade& t)
{
cout << setw(5) << t.Symbol << " ";
cout << setw(2) << t.Strat << " ";
cout << setw(2) << t.BuyDayOfMonth << " ";
cout << setw(7) << t.BuyPrice << " ";
cout << setw(2) << t.SellDayOfMonth << " ";
cout << setw(7) << t.SellPrice << " ";
cout << setw(6) << t.numshares << " ";
cout << setw(6) << t.NetProfit;
cout << endl;
}
void ListTradeHeader()
{ // ...+....2....+....3....+....4....+....5....+....6....+
// sssss st bd bbbbb.bb sd sssss.ss nnnnnn aaaaa.aa
cout << "Symbl ST BD BuyPrice SD SellPric Shares Profit" << endl;
}
// List all trades that match the long or short argument
void ListRawTrades(bool ls)
{
int cnt = 0;
if (ls)
cout << "All long trades" << endl;
else
cout << "All short trades" << endl;
cout << endl;
ListTradeHeader();
for (auto t : trades)
{
if (t.isLong == ls)
{
ListTrade(t); // List one matching trade
cnt++;
}
}
if (cnt == 0)
cout << "No matching trades" << endl;
cout << endl;
}
// Calculate total gains and losses
void TotalGainsandLosses()
{
int num_trades = 0;
int winning_trade_count = 0;
int losing_trade_count = 0;
double avg_winning_trade = 0;
double avg_losing_trade = 0;
double sum_winning_trades = 0;
double sum_losing_trades = 0;
Trade largest_winning_trade{};
double largest_win = 0;
Trade largest_losing_trade{};
double largest_loss = 0;
double winning_percent = 0;
double balance = starting_capital;
for (auto t : trades)
{
if (t.NetProfit > 0)
{
sum_winning_trades += t.NetProfit;
winning_trade_count++;
if (t.NetProfit > largest_win)
{
largest_win = t.NetProfit;
largest_winning_trade = t;
}
}
else
{
sum_losing_trades += t.NetProfit;
losing_trade_count++;
if (t.NetProfit < largest_loss)
{
largest_loss = t.NetProfit;
largest_losing_trade = t;
}
}
balance += t.NetProfit;
num_trades++;
}
avg_winning_trade = sum_winning_trades / (double)winning_trade_count;
avg_losing_trade = sum_losing_trades / (double)losing_trade_count;
winning_percent = (double)winning_trade_count / (double)num_trades * 100;
cout << "Total Gains = " << sum_winning_trades << endl;
cout << "Total Losses = " << sum_losing_trades << endl;
cout << "Winning trades = " << winning_trade_count << endl;
cout << "Losing trades = " << losing_trade_count << endl;
cout << "Total number of trades = " << num_trades << endl;
cout << "Average winning trade = " << avg_winning_trade << endl;
cout << "Average_losing_trade = " << avg_losing_trade << endl;
if (largest_win == 0)
cout << "There were no winning trades" << endl;
else
{
cout << "Largest winning trade" << endl;
ListTradeHeader();
ListTrade(largest_winning_trade);
}
if (largest_loss == 0)
cout << "There were no losing trades" << endl;
else
{
cout << "Largest losing trade" << endl;
ListTradeHeader();
ListTrade(largest_losing_trade);
}
cout << "Winning percent = " << winning_percent << endl;
cout << "Remaining capital = " << balance << endl;
cout << endl;
}
// Find most used strategy
// Does not account for ties
void FindMostUsedStrategy()
{
strat_map_t strat_map;
strat_map_t::iterator iter;
int most_used_cnt = 0;
int most_used_strat = 0;
// Iterate throught the trades
for (auto t : trades)
{ // Have we seen this strategy before?
iter = strat_map.find(t.Strat);
if (iter != strat_map.end())
{ // Yes, increment the count
iter->second++;
continue;
}
else
{ // No, new strategy
pair<int, int> item(t.Strat, 1);
strat_map.insert(item);
}
}
// Find the most used
for (auto s : strat_map)
{
if (s.second > most_used_cnt)
{
most_used_strat = s.first;
most_used_cnt = s.second;
}
}
cout << "Most used strategy = " << most_used_strat << endl;
cout << "It was used " << most_used_cnt << " times." << endl;
cout << endl;
}
// Sort trades from biggest profit to smallest profit
bool OrderByNetProfit(const Trade& t1, const Trade& t2)
{
return t1.NetProfit > t2.NetProfit;
}
int main()
{
if (!read_csv_file())
return 1;
// Sort vector biggest to smallest net amount
// We only need one sort for both short and long trades
sort(trades.begin(), trades.end(), OrderByNetProfit);
ListRawTrades(true); // List all long trades
ListRawTrades(false); // List all short trades
TotalGainsandLosses();
FindMostUsedStrategy();
}
All long trades
Symbl ST BD BuyPrice SD SellPric Shares Profit
FGD 1 10 3.25 11 3.75 500 250
FRD 3 20 9.85 24 9.92 300 21
All short trades
Symbl ST BD BuyPrice SD SellPric Shares Profit
AVH 2 16 5.25 18 15.18 150 1489.5
FRD 2 12 35.25 15 34.75 100 -50
Total Gains = 1760.5
Total Losses = -50
Winning trades = 3
Losing trades = 1
Total number of trades = 4
Average winning trade = 586.833
Average_losing_trade = -50
Largest winning trade
Symbl ST BD BuyPrice SD SellPric Shares Profit
AVH 2 16 5.25 18 15.18 150 1489.5
Largest losing trade
Symbl ST BD BuyPrice SD SellPric Shares Profit
FRD 2 12 35.25 15 34.75 100 -50
Winning percent = 75
Remaining capital = 4210.5
Most used strategy = 2
It was used 2 times.
BTW, the first record of the posted CSV file has an "l" in the long/short position.
Change this to a "1" or you will hang up on the input.
This is incredible! Excel has primarily been used for my tracking system. I just started learning C++ as I'm sure you can tell. I have been interested in quant trading and I am learning C++ with the goal in mind to create my own trading algorithm. I wanted to started with a Day Trading tracking system and build from there. I have been working on much simpler projects and decided to take a shot at the tracker. I really appreciate you taking time to explain it and thanks a lot for taking the time to write this out!
if its going to handle real data, you need to track your fees. selling for $5 profit after paying $15 or whatever twice (once to buy, once to sell) is a $25 loss not a $5 gain.
not sure what else you need, it looks close. Time == money they say, so I still think you may want to also display profit per time unit (per day? week? whatever) between buy and sell. A decent profit years later is eaten up by inflation and missed chances... but what I don't know about all this stuff would fill a library. I let the experts invest mine most of the time. I took the money and ran on a covid prediction though ... Ag :)
if its going to handle real data, you need to track your fees. selling for $5 profit after paying $15 or whatever twice (once to buy, once to sell) is a $25 loss not a $5 gain.
Any system would indeed need to take into account costs of trades.
However, brokerage applies to the parcel of stocks being traded not each one individually. If the $5 profit was on selling 1000 shares then brokerage at $15 (x2) is a pittance. Depending on local tax rules that would be a sweet $4970. ( or a sour <$5030> if each sold was a $5 down )