Skip to content

Commit

Permalink
Added .csv support.
Browse files Browse the repository at this point in the history
You can now use the long term exports from Binance
  • Loading branch information
Nubebuster committed Apr 2, 2021
1 parent 7fbcceb commit 348630b
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 22 deletions.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,28 @@ https://github.com/Nubebuster/CryptoProfitTracker/releases
4. Go to the 'Main' tab and set your pairing. For example: ADAUSDT

## How to export data from Binance

#### For a max range of 3 months:
This will generate a .xlsx file which you can use for this program
1. Go to your trade history
2. Click on the tab 'Trade History'
3. Click on 'Export Recent Trade History'

This will generate a .xlsx file which you can use for this program

#### Limitless (max 3 exports per month, binance cap)
This will generate a .csv file which you can use for this program
1. Go to your trade history
2. Click on the tab 'Trade History'
3. Click on 'Generate All Trade Statements'


## TODO
- Test accurate valuation for non xUSDT pairs
- Add support for mixing trading pairs. For example: ETHUSDT in conjunction with ETHBTC
- Add more exchange export support
- Add profit calculation for all trading pairs
- UI with graphs to plot your profits over time
- Add support for .csv binance export
# Troubleshooting
If the program does not work properly, please run it with a command line to see error stacktraces.
These stacktraces can be reported in the github issues section of this repository.
These stacktraces can be reported in the github issues section of this repository.
Be sure to explain how to reproduce the problem. Also include stacktraces.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.nubebuster.cryptoprofittracker</groupId>
<artifactId>cryptoprofittracker</artifactId>
<version>0.0.1</version>
<version>0.0.3</version>
<build>
<plugins>
<plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.swing.*;
import java.io.File;
import java.io.FileWriter;
import java.io.*;
import java.math.BigDecimal;
import java.math.MathContext;
import java.rmi.UnexpectedException;
Expand Down Expand Up @@ -69,14 +68,34 @@ public static void main(String[] args) {
ui.printCalculationsButton.setEnabled(true);
return;
}
OPCPackage pkg = OPCPackage.open(dataFile);
Workbook wb = new XSSFWorkbook(pkg);
Sheet sheet = wb.getSheetAt(0);
Iterator<Row> rows = sheet.rowIterator();
List<TradeOrder> orders = null;
if (dataFile.getName().endsWith(".xlsx")) {
OPCPackage pkg = OPCPackage.open(dataFile);
Workbook wb = new XSSFWorkbook(pkg);
Sheet sheet = wb.getSheetAt(0);
Iterator<Row> rows = sheet.rowIterator();
orders = parseOrders(ui.ticker.getText().toUpperCase(), rows);
try {
pkg.close();
} catch (FileNotFoundException ex) {
//if its open in another program
}
} else if (dataFile.getName().endsWith(".csv")) {
List<String> data = new ArrayList<String>();
BufferedReader br = new BufferedReader(new FileReader(dataFile));
String line = "";
while ((line = br.readLine()) != null)
data.add(line);
orders = parseOrders(ui.ticker.getText().toUpperCase(), data);
} else {
System.err.println("Unsupported data format. Current support: [.xlsx, .csv]");
ui.output.setText("Unsupported data format. Current support: [.xlsx, .csv]");
ui.printCalculationsButton.setEnabled(true);
return;
}
BinanceProfitTracker binanceProfitTracker = new BinanceProfitTracker(ui, ui.apiKeyTextField.getText(),
ui.secretKeyTextField.getText());
binanceProfitTracker.printCalculations(ui.ticker.getText(), bnbFee, rows);
pkg.close();
binanceProfitTracker.printCalculations(ui.ticker.getText().toUpperCase(), bnbFee, orders);
} catch (Exception ex) {
ex.printStackTrace();
}
Expand All @@ -95,7 +114,7 @@ public static void main(String[] args) {
ui.secretKeyTextField.getText() + "\ndataFile=" + ui.dataTextField.getText() + "\nNote: this file should not be edited manually.");
fr.flush();
fr.close();
System.out.println("Saved data to " + configFile.getPath());
System.out.println("Saved settings to " + configFile.getPath());
} catch (Exception e) {
e.printStackTrace();
}
Expand Down Expand Up @@ -123,12 +142,44 @@ public BinanceApiRestClient getBinanceClient() {
return client;
}

public void printCalculations(String pair, double bnbFeeValue, Iterator<Row> rows) throws Exception {
/**
* For parsing .csv format
*
* @param pair
* @param data
* @return
*/
private static List<TradeOrder> parseOrders(String pair, List<String> data) {
List<TradeOrder> orders = new ArrayList<TradeOrder>();
for (String r : data) {
if (r.startsWith("Date")) //headers
continue;
String[] row = r.replaceAll("(\"[^\",]+),([^\"]+\")", "$1$2").replace("\"", "").split(",");
String linePair = row[1];
if (!linePair.equals(pair))
continue;

long oldest = Long.MAX_VALUE;
long newest = Long.MIN_VALUE;
long time = CryptoProfitTrackerUtils.convertToTimeStamp(row[0]);
boolean buy = row[2].equals("BUY");
double price = Double.parseDouble(row[3]);
double amount = Double.parseDouble(row[4].replaceAll("[^\\d.]", ""));
double total = Double.parseDouble(row[5].replaceAll("[^\\d.]", ""));
double fee = Double.parseDouble(row[6].replaceAll("[^\\d.]", ""));
String feeCoin = row[6].replaceAll("[\\d.]", "");
orders.add(new TradeOrder(pair, buy, price, amount, total, fee, feeCoin, time));
}
return orders;
}

/**
* For parsing .xlsx format
*
* @param pair
* @param rows
* @return
*/
private static List<TradeOrder> parseOrders(String pair, Iterator<Row> rows) {
List<TradeOrder> orders = new ArrayList<TradeOrder>();
while (rows.hasNext()) {
Row row = rows.next();
if (row.getRowNum() == 0) //headers
Expand All @@ -138,9 +189,6 @@ public void printCalculations(String pair, double bnbFeeValue, Iterator<Row> row
continue;

long time = CryptoProfitTrackerUtils.convertToTimeStamp(row.getCell(0).getStringCellValue());
if (time < oldest) oldest = time;
if (time > newest) newest = time;

boolean buy = row.getCell(2).getStringCellValue().equals("BUY");
double price = Double.parseDouble(row.getCell(3).getStringCellValue());
double amount = Double.parseDouble(row.getCell(4).getStringCellValue());
Expand All @@ -150,8 +198,26 @@ public void printCalculations(String pair, double bnbFeeValue, Iterator<Row> row

orders.add(new TradeOrder(pair, buy, price, amount, total, fee, feeCoin, time));
}
return orders;
}

// //collect all candles from the first to last transaction to be able to convert at timestamps without querying.
/**
* @param pair needs to be in upper case. Example: ADAUSDT
* @param bnbFeeValue percentage formatted to double
* @param orders
* @throws Exception
*/
public void printCalculations(String pair, double bnbFeeValue, List<TradeOrder> orders) throws Exception {

// //collect all candles from the first to last transaction to be able to convert at timestamps without querying.
// long oldest = Long.MAX_VALUE;
// long newest = Long.MIN_VALUE;
// for(TradeOrder order : getOrders(pair, rows)) {
// long time = order.getTime();
// if (time < oldest) oldest = time;
// if (time > newest) newest = time;
// }
//
// List<Candlestick> candles = candleStickCollector.getCandlesCollectWhenMissing(pair, oldest - CryptoProfitTrackerUtils.convertCandleStickIntervalToMs(CACHE_PRECISION), newest + CryptoProfitTrackerUtils.convertCandleStickIntervalToMs(CACHE_PRECISION),
// CACHE_PRECISION);

Expand Down Expand Up @@ -186,7 +252,7 @@ public void printCalculations(String pair, double bnbFeeValue, Iterator<Row> row
}

log("Data for " + pair);
log("#Orders (BUY+SELL): " + orders.size());
log("#Trades (BUY+SELL): " + orders.size());
log("Volume: " + roundedToSignificance(volume));
log("Sub Total Profit: " + roundedToSignificance(cumProfit));

Expand All @@ -200,7 +266,7 @@ public void printCalculations(String pair, double bnbFeeValue, Iterator<Row> row
}

/**
* @param candles to get the price from
* @param candles to get the price from
* @param timestamp of the price you want to know
* @returns the closing price of the candle. -1 if no candle was found.
* You can use {@link #loadHistoricalPrice(String, long)} if this function returns -1.
Expand Down

0 comments on commit 348630b

Please sign in to comment.