diff --git a/nbproject/project.properties b/nbproject/project.properties
index 6037054..aaab35f 100644
--- a/nbproject/project.properties
+++ b/nbproject/project.properties
@@ -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=
diff --git a/src/opensesim/gui/account/StatusPanel.form b/src/opensesim/gui/account/StatusPanel.form
new file mode 100644
index 0000000..c638b68
--- /dev/null
+++ b/src/opensesim/gui/account/StatusPanel.form
@@ -0,0 +1,28 @@
+
+
+
diff --git a/src/opensesim/gui/account/StatusPanel.java b/src/opensesim/gui/account/StatusPanel.java
new file mode 100644
index 0000000..9a8f60f
--- /dev/null
+++ b/src/opensesim/gui/account/StatusPanel.java
@@ -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")
+ // //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)
+ );
+ }// //GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/opensesim/world/Account.java b/src/opensesim/world/Account.java
index a7dbca2..034f15a 100644
--- a/src/opensesim/world/Account.java
+++ b/src/opensesim/world/Account.java
@@ -41,19 +41,21 @@ import org.json.JSONObject;
public class Account {
HashMap assets = new HashMap<>();
- HashMap assets_avail = new HashMap<>();
+ HashMap assets_bound = new HashMap<>();
HashMap 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 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 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);
+
+ }
+
}
diff --git a/src/opensesim/world/SimpleTrader.java b/src/opensesim/world/SimpleTrader.java
index e55c6ec..b496b39 100644
--- a/src/opensesim/world/SimpleTrader.java
+++ b/src/opensesim/world/SimpleTrader.java
@@ -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;
}
diff --git a/src/opensesim/world/TradingEngine.java b/src/opensesim/world/TradingEngine.java
index 4bdb44e..1d87b76 100644
--- a/src/opensesim/world/TradingEngine.java
+++ b/src/opensesim/world/TradingEngine.java
@@ -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;