Work on correct calculation of available money with margin
This commit is contained in:
parent
a2e5143c64
commit
2d7feed929
@ -1,4 +1,4 @@
|
||||
#Fri, 04 Jan 2019 17:38:20 +0100
|
||||
#Sat, 05 Jan 2019 10:43:36 +0100
|
||||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.processors.list=
|
||||
|
28
src/opensesim/gui/account/StatusPanel.form
Normal file
28
src/opensesim/gui/account/StatusPanel.form
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
</Form>
|
78
src/opensesim/gui/account/StatusPanel.java
Normal file
78
src/opensesim/gui/account/StatusPanel.java
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 7u83 <7u83@mail.ru>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package opensesim.gui.account;
|
||||
|
||||
import opensesim.world.Account;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author 7u83 <7u83@mail.ru>
|
||||
*/
|
||||
public class StatusPanel extends javax.swing.JPanel {
|
||||
|
||||
/**
|
||||
* Creates new form StatusPanel
|
||||
*/
|
||||
public StatusPanel() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
public StatusPanel(Account account) {
|
||||
this();
|
||||
setAccount(account);
|
||||
}
|
||||
|
||||
private Account account;
|
||||
|
||||
public void setAccount(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 400, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 300, Short.MAX_VALUE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -41,19 +41,21 @@ import org.json.JSONObject;
|
||||
public class Account {
|
||||
|
||||
HashMap<AbstractAsset, Double> assets = new HashMap<>();
|
||||
HashMap<AbstractAsset, Double> assets_avail = new HashMap<>();
|
||||
HashMap<AbstractAsset, Double> assets_bound = new HashMap<>();
|
||||
HashMap<AbstractAsset, Double> stop_los = new HashMap<>();
|
||||
|
||||
public double margin_bound=0.0;
|
||||
|
||||
public double margin_bound = 0.0;
|
||||
|
||||
Trader owner;
|
||||
//public Exchange exchange = null;
|
||||
|
||||
|
||||
private World world;
|
||||
|
||||
|
||||
|
||||
|
||||
private RealWorld world;
|
||||
private Exchange exchange;
|
||||
|
||||
public Exchange getExchange() {
|
||||
return exchange;
|
||||
}
|
||||
|
||||
private boolean unlimited = false;
|
||||
|
||||
public boolean isUnlimied() {
|
||||
@ -63,7 +65,6 @@ public class Account {
|
||||
void setUnlimied(boolean unlimied) {
|
||||
this.unlimited = unlimied;
|
||||
}
|
||||
|
||||
|
||||
private double leverage = 0.0;
|
||||
|
||||
@ -80,7 +81,7 @@ public class Account {
|
||||
}
|
||||
|
||||
public Map<AbstractAsset, Double> getAssetsAavail() {
|
||||
return Collections.unmodifiableMap(assets_avail);
|
||||
return Collections.unmodifiableMap(assets_bound);
|
||||
}
|
||||
|
||||
public Trader getOwner() {
|
||||
@ -88,34 +89,40 @@ public class Account {
|
||||
}
|
||||
|
||||
protected Account(World world) {
|
||||
this.world = world;
|
||||
this(world, null, null);
|
||||
}
|
||||
|
||||
protected Account(World world, JSONObject cfg) {
|
||||
this.world = world;
|
||||
protected Account(World world, Exchange exchange, JSONObject cfg) {
|
||||
this.world = (RealWorld) world;
|
||||
if (exchange == null) {
|
||||
this.exchange = world.getDefaultExchange();
|
||||
}
|
||||
if (cfg == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public Double getMargin(AbstractAsset currency) {
|
||||
/* Double d = this.getAssetDebt(world.getDefaultExchange(), currency);
|
||||
/* Double d = this.getAssetDebt(world.getDefaultExchange(), currency);
|
||||
|
||||
Double f = this.getFinalBalance(currency) * getLeverage() ;
|
||||
System.out.printf("Debth %f - Final: %f Return margin %f\n", d,f, f-d);
|
||||
|
||||
return f-d;*/
|
||||
|
||||
return this.getFinalBalance(currency) * getLeverage() + this.getFinalBalance(currency)
|
||||
|
||||
return this.getFinalBalance(currency) * getLeverage() + this.getFinalBalance(currency)
|
||||
- this.getAssetDebt(world.getDefaultExchange(), currency);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
synchronized void add(AssetPack pack) {
|
||||
assets.put(pack.asset, get(pack.asset) + pack.volume);
|
||||
assets_avail.put(pack.asset, getAvail(pack.asset) + pack.volume);
|
||||
assets_bound.put(pack.asset, getAvail(pack.asset) + pack.volume);
|
||||
}
|
||||
|
||||
synchronized void sub(AssetPack pack) {
|
||||
assets.put(pack.asset, get(pack.asset) - pack.volume);
|
||||
// assets_avail.put(pack.asset, getAvail(pack.asset) - pack.volume);
|
||||
// assets_bound.put(pack.asset, getAvail(pack.asset) - pack.volume);
|
||||
}
|
||||
|
||||
public double get(AbstractAsset asset) {
|
||||
@ -123,23 +130,22 @@ public class Account {
|
||||
}
|
||||
|
||||
public double getAvail(AbstractAsset asset) {
|
||||
if (this.getLeverage()>0){
|
||||
if (this.getLeverage() > 0) {
|
||||
Double margin = this.getMargin(world.getDefaultCurrency());
|
||||
|
||||
|
||||
AssetPair ap = world.getAssetPair(asset, world.getDefaultCurrency());
|
||||
|
||||
|
||||
|
||||
return margin / world.getDefaultExchange().getAPI(ap).getLastQuote().price;
|
||||
}
|
||||
|
||||
|
||||
return 0.0;
|
||||
|
||||
//return assets_avail.getOrDefault(asset, 0.0);
|
||||
|
||||
//return assets_bound.getOrDefault(asset, 0.0);
|
||||
}
|
||||
|
||||
public void addAvail(AbstractAsset asset, double val) {
|
||||
double avail = getAvail(asset);
|
||||
assets_avail.put(asset, (avail + val));
|
||||
assets_bound.put(asset, (avail + val));
|
||||
}
|
||||
|
||||
HashSet<EventListener> listeners = new HashSet<>();
|
||||
@ -163,7 +169,7 @@ public class Account {
|
||||
|
||||
public Double getAssetDebt(Exchange ex, AbstractAsset currency) {
|
||||
Double result = 0.0;
|
||||
System.out.printf("Enter depth rechner %f\n", result);
|
||||
|
||||
for (AbstractAsset a : assets.keySet()) {
|
||||
if (a.equals(currency)) {
|
||||
continue;
|
||||
@ -177,17 +183,16 @@ public class Account {
|
||||
Double v = get(a) * api.last_quote.price;
|
||||
Double sl = this.calcStopLoss(a);
|
||||
Double n = get(a);
|
||||
if (n==0.0)
|
||||
if (n == 0.0) {
|
||||
continue;
|
||||
|
||||
System.out.printf("Asset: %s - %f %f %f\n", a.getSymbol(),n, v, sl*n);
|
||||
|
||||
|
||||
result = result + (v-sl*n);
|
||||
System.out.printf("Result is now %f\n", result);
|
||||
}
|
||||
|
||||
// System.out.printf("Asset: %s - %f %f %f\n", a.getSymbol(), n, v, sl * n);
|
||||
result = result + (v - sl * n);
|
||||
// System.out.printf("Result is now %f\n", result);
|
||||
|
||||
}
|
||||
System.out.printf("Return Dresult %f\n", result);
|
||||
// System.out.printf("Return Dresult %f\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -200,7 +205,8 @@ public class Account {
|
||||
* @return final balance
|
||||
*
|
||||
*/
|
||||
public Double getFinalBalance(Exchange ex, AbstractAsset currency) {
|
||||
public Double getFinalBalance(Exchange ex, AbstractAsset currency,
|
||||
boolean bound) {
|
||||
|
||||
Double result = get(currency);
|
||||
for (AbstractAsset a : assets.keySet()) {
|
||||
@ -212,18 +218,25 @@ public class Account {
|
||||
if (pair == null) {
|
||||
continue;
|
||||
}
|
||||
v = get(a);
|
||||
if (v==0.0)
|
||||
v = get(a) + (bound ? getBound(a) : 0.0);
|
||||
|
||||
if (v == 0.0) {
|
||||
continue;
|
||||
|
||||
|
||||
TradingEngine api = (TradingEngine) ex.getAPI(pair);
|
||||
//v = get(a) * api.last_quote.price;
|
||||
}
|
||||
|
||||
result = result + v*api.last_quote.price;
|
||||
TradingEngine api = (TradingEngine) ex.getAPI(pair);
|
||||
result = result + v * api.last_quote.price;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Double getBound(AbstractAsset asset){
|
||||
return assets_bound.getOrDefault(asset, 0.0);
|
||||
}
|
||||
|
||||
void addBound(AbstractAsset asset, Double vol){
|
||||
assets_bound.put(asset, getBound(asset)+vol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the final balance as if all assets would be sold ob the default
|
||||
@ -234,7 +247,7 @@ public class Account {
|
||||
* @return final balance
|
||||
*/
|
||||
public Double getFinalBalance(AbstractAsset currency) {
|
||||
return getFinalBalance(world.getDefaultExchange(), currency);
|
||||
return getFinalBalance(this.getExchange(), currency, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,22 +275,58 @@ public class Account {
|
||||
|
||||
TradingEngine api = (TradingEngine) ex.getAPI(pair);
|
||||
Double v = get(a) * api.last_quote.price;
|
||||
e = e+v;
|
||||
|
||||
e = e + v;
|
||||
|
||||
}
|
||||
|
||||
return -(double)e / (double)get(asset);
|
||||
|
||||
return -(double) e / (double) get(asset);
|
||||
}
|
||||
|
||||
public Double calcStopLoss(AbstractAsset asset){
|
||||
return calcStopLoss(world.getDefaultExchange(),asset,world.getDefaultAssetPair().getCurrency());
|
||||
public Double calcStopLoss(AbstractAsset asset) {
|
||||
return calcStopLoss(world.getDefaultExchange(), asset, world.getDefaultAssetPair().getCurrency());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the world this account belongs to
|
||||
*
|
||||
* @return world
|
||||
*/
|
||||
public World getWorld(){
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
private boolean isLeveraged() {
|
||||
return getLeverage() > 0.0;
|
||||
}
|
||||
|
||||
boolean isCovered(AssetPair pair, double volume, double limit) {
|
||||
if (this.isUnlimied()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.isLeveraged()) {
|
||||
if (limit == 0.0) {
|
||||
// an unlimited order is always considered to be
|
||||
// covereable. When the trade comes to execution,
|
||||
// the limits will be checked.
|
||||
return true;
|
||||
}
|
||||
if (volume < 0) {
|
||||
// It's a limited sell order, we have just to check
|
||||
// if a sufficient amount of assets is available
|
||||
return getAvail(pair.getAsset()) + volume > 0;
|
||||
}
|
||||
// Check if enough money is available to cover the
|
||||
// entiere volume to by
|
||||
return getAvail(pair.getCurrency()) >= limit * volume;
|
||||
}
|
||||
|
||||
|
||||
Double margin = this.getMargin(pair.getCurrency());
|
||||
System.out.printf("Margin: %f > %f\n", margin, Math.abs(volume * limit));
|
||||
|
||||
return margin > 0; //Math.abs(volume * limit);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -105,17 +105,16 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
|
||||
|
||||
pack = new AssetPack(p.getCurrency(), 1000);
|
||||
account_b.add(pack);
|
||||
account_b.setLeverage(10.0);
|
||||
account_b.setLeverage(9.0);
|
||||
|
||||
pack = new AssetPack(p.getCurrency(), 1234567890);
|
||||
account_1.add(pack);
|
||||
account_1.setLeverage(0.0);
|
||||
account_1.setUnlimied(true);
|
||||
|
||||
long delay = (long) (1000.0f * getWorld().randNextFloat(15.0f, 15.7f));
|
||||
long delay = (long) (1000.0f * getWorld().randNextFloat(5.0f, 5.7f));
|
||||
setStatus(String.format("Initial delay: Sleeping for %d seconds.", delay));
|
||||
|
||||
|
||||
|
||||
getWorld().schedule(this, delay);
|
||||
|
||||
// long delay = (long) (getRandom(initial_delay[0], initial_delay[1]) * 1000);
|
||||
@ -133,37 +132,30 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
|
||||
|
||||
long diff = getWorld().currentTimeMillis() - last_time;
|
||||
last_time = getWorld().currentTimeMillis();
|
||||
|
||||
AssetPair p = getWorld().getDefaultAssetPair();
|
||||
|
||||
|
||||
ex = getWorld().getDefaultExchange();
|
||||
|
||||
AssetPair p = getWorld().getDefaultAssetPair();
|
||||
|
||||
ex = getWorld().getDefaultExchange();
|
||||
api = ex.getAPI(p);
|
||||
|
||||
AssetPair msftp = getWorld().getAssetPair(getWorld().getAssetBySymbol("MSFT"),
|
||||
getWorld().getAssetBySymbol("EUR"));
|
||||
TradingAPI mapi = ex.getAPI(msftp);
|
||||
|
||||
AssetPair msftp = getWorld().getAssetPair(getWorld().getAssetBySymbol("MSFT"),
|
||||
getWorld().getAssetBySymbol("EUR"));
|
||||
TradingAPI mapi = ex.getAPI(msftp);
|
||||
|
||||
Order ob = api.createOrder(account_b, Order.Type.BUYLIMIT, 20, 100);
|
||||
|
||||
//Order mob = mapi.createOrder(account_b, Order.Type.SELLLIMIT, 80, 100);
|
||||
|
||||
Order oa = api.createOrder(account_1, Order.Type.SELLLIMIT, 100, 100);
|
||||
//Order oaaa = mapi.createOrder(account_1, Order.Type.BUYLIMIT, 100, 100);
|
||||
|
||||
Order oa = api.createOrder(account_1, Order.Type.SELLLIMIT, 100, 200);
|
||||
//Order oaaa = mapi.createOrder(account_1, Order.Type.BUYLIMIT, 100, 100);
|
||||
|
||||
//Order oax = mapi.createOrder(account_1, Order.Type.BUYLIMIT, 100, 100);
|
||||
|
||||
// Order oa = api.createOrder(account_1, Order.Type.BUYLIMIT, 100, 10.0);
|
||||
// Order ob = api.createOrder(account_1, Order.Type.BUYLIMIT, 100, 9.0);
|
||||
// Order oc = api.createOrder(account_1, Order.Type.BUYLIMIT, 100, 8.0);
|
||||
// Order o2 = api.createOrder(account_10, Order.Type.SELLLIMIT, 300, 1.0);
|
||||
//Order ou = api.createOrder(account_1, Order.Type.BUYLIMIT, 30, 10.0);
|
||||
// Order o1 = api.createOrder(account, Order.Type.SELLLIMIT, 250, 278);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
|
||||
System.out.printf("Here we are: %d - [%d]\n", Thread.currentThread().getId(), diff);
|
||||
getWorld().schedule(this, 1000);
|
||||
@ -174,7 +166,7 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
|
||||
api = ex.getAPI(p);
|
||||
Order o = api.createOrder(account, Order.Type.BUY, 112.987123, limit);
|
||||
limit += 12;
|
||||
*/
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -437,32 +437,24 @@ class TradingEngine implements TradingAPI {
|
||||
} else {
|
||||
switch (type) {
|
||||
case BUYLIMIT: {
|
||||
Double avail;
|
||||
|
||||
// verfify available currency for a buy limit order
|
||||
AbstractAsset currency = this.assetpair.getCurrency();
|
||||
if (account.getLeverage() == 0.0) {
|
||||
avail = account.getAvail(currency);
|
||||
account.addAvail(currency, -(v * l));
|
||||
|
||||
} else {
|
||||
|
||||
avail = account.getMargin(assetpair.getCurrency());
|
||||
|
||||
|
||||
if (!account.isCovered(assetpair, volume, limit)){
|
||||
System.out.printf("Not enough funds\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// return if not enough funds are available
|
||||
if (avail < v * l) {
|
||||
o = new Order(this, account, type, v, l);
|
||||
o.status = Order.Status.ERROR;
|
||||
// if (avail < v * l) {
|
||||
// o = new Order(this, account, type, v, l);
|
||||
// o.status = Order.Status.ERROR;
|
||||
|
||||
System.out.printf("Error order no funds\n");
|
||||
// System.out.printf("Error order no funds\n");
|
||||
// return o;
|
||||
}
|
||||
// }
|
||||
|
||||
account.margin_bound += v * l;
|
||||
// reduce the available money
|
||||
// account.assets_avail.put(currency, avail - v * l);
|
||||
// account.assets_bound.put(currency, avail - v * l);
|
||||
|
||||
//account.addMarginAvail(currency, -((v * l)/account.getLeverage()));
|
||||
order_limit = l;
|
||||
@ -482,7 +474,7 @@ class TradingEngine implements TradingAPI {
|
||||
}
|
||||
|
||||
// All available monney is assigned to this unlimited order
|
||||
account.assets_avail.put(currency, 0.0);
|
||||
account.assets_bound.put(currency, 0.0);
|
||||
// we "mis"use order_limit to memorize occupied ammount \
|
||||
// of currency
|
||||
order_limit = avail;
|
||||
@ -501,7 +493,7 @@ class TradingEngine implements TradingAPI {
|
||||
// not enough items of asset (shares) available
|
||||
// return null;
|
||||
}
|
||||
account.assets_avail.put(asset, avail - v);
|
||||
account.assets_bound.put(asset, avail - v);
|
||||
order_limit = l;
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user