Compare commits

...

41 Commits

Author SHA1 Message Date
7u83 8279033d74 Fixed name of StockAsset and inserted Sockasset to example 2020-10-23 10:02:30 +02:00
7u83 2e1a53789f Added some comments 2020-10-23 09:45:44 +02:00
7u83 b084e0a156 Asset folder is lower case 2020-10-23 09:15:42 +02:00
7u83 2241822b26 Loads Ivy 2020-10-23 09:15:14 +02:00
7u83 d63ee05b5d Added example.json to run with Cli 2020-07-25 03:08:08 +02:00
7u83 27c08eee39 Removed interfaces Asset. Refactoring 2020-07-25 01:12:53 +02:00
7u83 2443b984cf Added cli sub directory 2020-07-25 01:04:56 +02:00
7u83 7359e15a54 Removed old dependencies 2020-07-25 00:05:21 +02:00
7u83 8ab7c51101 Recompiled 2020-07-24 23:55:06 +02:00
7u83 9a4548ab35 Removed a function 2019-05-13 08:54:40 +02:00
7u83 9e1f1b8580 Better naming for "outer" class 2019-05-09 17:51:46 +02:00
7u83 54ec792c13 Som reformatting 2019-05-09 15:07:25 +02:00
7u83 97366b8335 Som reformatting 2019-05-06 17:11:53 +02:00
7u83 9a88f42b7e more work on stop loss 2019-05-06 13:49:26 +02:00
7u83 f5552c7b5b Account improved
divided into interface and implementation
2019-01-14 08:43:24 +01:00
7u83 703fe209b2 Correct SL calculation 2019-01-08 19:32:53 +01:00
7u83 236138a822 binding function works now for short and long
with and without leverage
2019-01-08 16:52:04 +01:00
7u83 8f35e767bd Work on asset binding when creating orders 2019-01-08 09:24:08 +01:00
7u83 2d7feed929 Work on correct calculation of available money with margin 2019-01-05 11:05:18 +01:00
7u83 a2e5143c64 more work on stop loss 2019-01-04 19:09:20 +01:00
7u83 b5c6d45f66 Fixed stop loss calculation 2019-01-04 08:29:45 +01:00
7u83 b193d69f52 More work on stop loss 2019-01-03 18:59:17 +01:00
7u83 fcdae01a8b Added ERROR status and message String with getter and setter 2019-01-02 20:03:55 +01:00
7u83 0cedbbc3d4 Work on stop loss 2019-01-01 19:20:35 +01:00
7u83 3f43ff6f29 Added some java doc 2019-01-01 14:48:46 +01:00
7u83 a1c1196ba1 no account checking (for test only) 2019-01-01 14:23:01 +01:00
7u83 0b62def911 Opens new windows for second asset(for test only) 2019-01-01 14:22:38 +01:00
7u83 0177510961 display caclulated stop loss (for test only) 2019-01-01 14:21:41 +01:00
7u83 641285fafb function to calculate stop loss 2019-01-01 14:20:41 +01:00
7u83 215fb5e074 renamed to getFinalBalance
Introduced function GetAssetDebt
2018-12-31 23:34:57 +01:00
7u83 22e77665ee Test stuff 2018-12-31 14:12:14 +01:00
7u83 f7c2b6266e Margin display 2018-12-31 14:12:02 +01:00
7u83 3a01f672eb Interface for get asset pair 2018-12-31 14:11:40 +01:00
7u83 3853beac19 Margin stuff 2018-12-31 14:11:18 +01:00
7u83 d661de2892 No change 2018-12-31 14:10:43 +01:00
7u83 6eb9ab8ff9 Proxy funkction for getAssetPair by assets 2018-12-31 14:09:18 +01:00
7u83 a9ad772112 creates account with world parameter 2018-12-31 14:08:44 +01:00
7u83 e99aa62c59 Stuff to calculate margin and value 2018-12-31 14:08:06 +01:00
7u83 401b6ce2f9 Constructors are protected 2018-12-31 14:07:37 +01:00
7u83 904b4a1016 Cunstruct account with world parameter 2018-12-31 14:06:18 +01:00
7u83 844a57df27 New function to asset pair by assets 2018-12-31 14:05:02 +01:00
41 changed files with 987 additions and 319 deletions

View File

@ -130,7 +130,7 @@
<delete file="${store.dir}/temp_final.jar"/>
</target>
<property name="ivy.install.version" value="2.1.0-rc2" />
<property name="ivy.install.version" value="2.5.0" />
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME" />
</condition>
@ -142,7 +142,7 @@
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
<get src="https://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>

11
ivy.xml
View File

@ -11,18 +11,7 @@
<!-- https://mvnrepository.com/artifact/javax.help/javahelp -->
<dependency org="javax.help" name="javahelp" rev="2.0.05"/>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency org="com.fasterxml.jackson.core" name="jackson-core" rev="2.9.7"/>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.9.7"/>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<!--<dependency org="com.fasterxml.jackson.core" name="jackson-annotations" rev="2.9.7"/>-->
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency org="com.google.code.gson" name="gson" rev="2.8.5"/>
</dependencies>

View File

@ -155,18 +155,6 @@ is divided into following sections:
<istrue value="${not.archive.disabled}"/>
</or>
</condition>
<condition property="do.mkdist">
<and>
<isset property="do.archive"/>
<isset property="libs.CopyLibs.classpath"/>
<not>
<istrue value="${mkdist.disabled}"/>
</not>
<not>
<istrue value="${modules.supported.internal}"/>
</not>
</and>
</condition>
<condition property="do.archive+manifest.available">
<and>
<isset property="manifest.available"/>
@ -1194,13 +1182,27 @@ is divided into following sections:
<attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
</manifest>
</target>
<target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.mkdist" name="-do-jar-copylibs">
<target depends="init,compile" name="-check-do-mkdist">
<condition property="do.mkdist">
<and>
<isset property="do.archive"/>
<isset property="libs.CopyLibs.classpath"/>
<not>
<istrue value="${mkdist.disabled}"/>
</not>
<not>
<available file="${build.classes.dir}/module-info.class"/>
</not>
</and>
</condition>
</target>
<target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-check-do-mkdist" if="do.mkdist" name="-do-jar-copylibs">
<j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
<echo level="info">To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo level="info">java -jar "${dist.jar.resolved}"</echo>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.archive" name="-do-jar-jar" unless="do.mkdist">
<target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-check-do-mkdist" if="do.archive" name="-do-jar-jar" unless="do.mkdist">
<j2seproject1:jar manifest="${tmp.manifest.file}"/>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<property location="${dist.jar}" name="dist.jar.resolved"/>

View File

@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=8064a381@1.79.1.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=65c6cbee
nbproject/build-impl.xml.script.CRC32=ae093a94
nbproject/build-impl.xml.stylesheet.CRC32=3a2fa800@1.89.1.48
nbproject/build-impl.xml.script.CRC32=afd0a16a
nbproject/build-impl.xml.stylesheet.CRC32=f89f7d21@1.95.0.48

View File

@ -1,4 +1,4 @@
#Sat, 29 Dec 2018 21:04:02 +0100
#Sat, 25 Jul 2020 03:07:19 +0200
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
@ -114,4 +114,4 @@ source.encoding=UTF-8
src.dir=src
test.src.dir=test
ivy.home=/usr/share/java
ivy.classpath=lib/commons-cli-1.0-javadoc.jar\:lib/commons-cli-1.0-sources.jar\:lib/commons-cli-1.0.jar\:lib/commons-lang-2.0-javadoc.jar\:lib/commons-lang-2.0-sources.jar\:lib/commons-lang-2.0.jar\:lib/commons-logging-1.0.jar\:lib/gson-2.8.5-javadoc.jar\:lib/gson-2.8.5-sources.jar\:lib/gson-2.8.5.jar\:lib/jackson-annotations-2.9.0.jar\:lib/jackson-core-2.9.7-javadoc.jar\:lib/jackson-core-2.9.7-sources.jar\:lib/jackson-core-2.9.7.jar\:lib/jackson-databind-2.9.7-javadoc.jar\:lib/jackson-databind-2.9.7-sources.jar\:lib/jackson-databind-2.9.7.jar\:lib/javahelp-2.0.05-javadoc.jar\:lib/javahelp-2.0.05-sources.jar\:lib/javahelp-2.0.05.jar\:lib/json-20160810-javadoc.jar\:lib/json-20160810-sources.jar\:lib/json-20160810.jar
ivy.classpath=lib/accessors-smart-1.1.jar\:lib/asm-5.0.3.jar\:lib/hamcrest-core-1.3.jar\:lib/javahelp-2.0.05-javadoc.jar\:lib/javahelp-2.0.05-sources.jar\:lib/javahelp-2.0.05.jar\:lib/json-20160810-javadoc.jar\:lib/json-20160810-sources.jar\:lib/json-20160810.jar\:lib/json-path-2.1.0.jar\:lib/json-smart-2.2.jar\:lib/junit-4.12.jar\:lib/mockito-core-1.9.5.jar\:lib/objenesis-1.0.jar\:lib/slf4j-api-1.7.13.jar

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2020, tube
* 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.cli;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import opensesim.world.GodWorld;
import opensesim.world.World;
/**
*
* @author tube
*/
public class Main {
public static void main(String[] args) throws IOException {
System.out.println("OpenSeSim Cli");
InputStream is;
is = Main.class.getResourceAsStream(
"/opensesim/resources/files/example.json"
);
// We have to bootstrap with a god world because
// there whould be no way to to initialize the world
GodWorld godworld = new GodWorld(is);
System.out.println("finished");
}
}

View File

@ -25,7 +25,7 @@
*/
package opensesim.gui;
import com.google.gson.Gson;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GraphicsDevice;
@ -94,6 +94,7 @@ public class SeSimApplication extends javax.swing.JFrame {
cfg = new JSONObject(Globals.prefs.get("world", "{}"));
godworld = new GodWorld(cfg);
godworld.addAssetPair("AAPL", "EUR");
godworld.addAssetPair("MSFT", "EUR");
// Get default screen and place our window
// to the center of this screen
@ -606,11 +607,12 @@ public class SeSimApplication extends javax.swing.JFrame {
+ "strategy: opensesim.world.SimpleTrader"
+ "}");
Trader t = godworld.createTrader(cfg);
t.start();
AccountDialog.runDialog(this, ((SimpleTrader)t).account_b);
AccountDialog.runDialog(this, ((SimpleTrader)t).account_s);
t.start();
AccountDialog.runDialog(this, ((SimpleTrader)t).account_1);
AccountDialog.runDialog(this, ((SimpleTrader)t).account_b);
updateGodWorld(godworld);
AssetPair p = godworld.getDefaultAssetPair();
@ -929,7 +931,10 @@ public class SeSimApplication extends javax.swing.JFrame {
AssetPair ap = godworld.getDefaultAssetPair();
opensesim.world.Exchange ex = godworld.getDefaultExchange();
opensesim.gui.orderbook.OrderBookDialog.runDialog(this, godworld, ex, ap);
AbstractAsset eu = godworld.getAssetBySymbol("EUR");
AssetPair ap2 = godworld.getAssetPair(godworld.getAssetBySymbol("MSFT"), eu);
opensesim.gui.orderbook.OrderBookDialog.runDialog(this, godworld, ex, ap2);
}//GEN-LAST:event_jCheckBoxMenuItem1ActionPerformed
@ -1048,10 +1053,10 @@ public class SeSimApplication extends javax.swing.JFrame {
// testing
Pojo p = new Pojo();
Gson g = new Gson();
String r = g.toJson(p);
// Gson g = new Gson();
// String r = g.toJson(p);
System.out.printf("GSON: %s\n", r);
// System.out.printf("GSON: %s\n", r);
JSONObject o = new JSONObject(p, new String[]{"name", "symbol"});
System.out.printf("OJSON: %s\n", o.toString(8));

View File

@ -23,18 +23,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="accountPanel1" min="-2" pref="400" max="-2" attributes="0"/>
</Group>
<Component id="accountPanel1" alignment="1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="accountPanel1" min="-2" pref="228" max="-2" attributes="0"/>
<EmptySpace min="0" pref="72" max="32767" attributes="0"/>
</Group>
<Component id="accountPanel1" alignment="0" pref="300" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>

View File

@ -25,7 +25,7 @@
*/
package opensesim.gui.account;
import opensesim.world.Account;
import opensesim.world.AccountImpl;
/**
*
@ -42,11 +42,12 @@ public class AccountDialog extends javax.swing.JDialog {
}
public static void runDialog(java.awt.Frame parent, Account account){
public static void runDialog(java.awt.Frame parent, AccountImpl account){
AccountDialog d;
d=new AccountDialog(parent, false);
d.accountPanel1.account=account;
d.accountPanel1.update();
account.addListener(d.accountPanel1);
d.setVisible(true);
}
@ -67,15 +68,11 @@ public class AccountDialog extends javax.swing.JDialog {
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(accountPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(accountPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(accountPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 228, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 72, Short.MAX_VALUE))
.addComponent(accountPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
);
pack();

View File

@ -17,11 +17,26 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="400" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="finalbalance" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="300" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" min="-2" pref="214" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="finalbalance" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="32" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
@ -36,9 +51,11 @@
<Component class="javax.swing.JTable" name="assetTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="2" rowCount="2">
<Table columnCount="4" rowCount="2">
<Column editable="false" title="Asset" type="java.lang.String"/>
<Column editable="false" title="Ammount" type="java.lang.String"/>
<Column editable="false" title="Margin" type="java.lang.String"/>
<Column editable="false" title="SL" type="java.lang.String"/>
</Table>
</Property>
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
@ -62,5 +79,15 @@
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" value="Final:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="finalbalance">
<Properties>
<Property name="text" type="java.lang.String" value="jLabel2"/>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -30,44 +30,61 @@ import javax.swing.table.DefaultTableModel;
import opensesim.util.scheduler.Event;
import opensesim.util.scheduler.EventListener;
import opensesim.world.AbstractAsset;
import opensesim.world.Account;
import opensesim.world.AccountImpl;
import opensesim.world.Asset;
/**
*
* @author tube
*/
public class AccountPanel extends javax.swing.JPanel implements EventListener{
public class AccountPanel extends javax.swing.JPanel implements EventListener {
/**
* Creates new form AccountPanel
*/
public AccountPanel() {
initComponents();
assetTable.setAutoCreateRowSorter(true);
assetTable.setAutoCreateRowSorter(true);
assetTable.getTableHeader().setReorderingAllowed(false);
}
public Account account;
public AccountImpl account;
void update() {
DefaultTableModel model;
model = (DefaultTableModel) this.assetTable.getModel();
Map<AbstractAsset, Double> am = account.getAssets();
Map<Asset, Double> am = account.getAssets();
int row = 0;
model.setRowCount(am.size());
for (AbstractAsset a : am.keySet()) {
Double val = account.get(a);
Double avail = account.getAvail(a);
String astr = val.toString()+"/"+avail.toString();
for (Asset a : am.keySet()) {
Double val = account.get((AbstractAsset) a,false);
Double avail = account.getBound((AbstractAsset) a);
String astr = val.toString() + "/" + avail.toString();
Double mval = account.getMargin((AbstractAsset) a);
// Double mavail = account.getMargin((AbstractAsset) a)-account.margin_bound;
String mastr = "xxx" ; //Double(0.0(.toString()+ "/" + mavail.toString();
Double sl = account.calcStopLoss((AbstractAsset) a);
// model.setValueAt(ob1.getAccount().getOwner().getName(), row, 0);
model.setValueAt(a.getSymbol(), row, 0);
model.setValueAt(astr, row, 1);
// model.setValueAt(mastr, row, 2);
model.setValueAt(sl.toString(), row, 3);
row++;
}
String fb;
Double margin = account.getMargin(account.getWorld().getDefaultCurrency());
fb = account.getFinalBalance().toString() + " Margin: " +
margin.toString();
this.finalbalance.setText(fb);
}
/**
@ -81,21 +98,23 @@ public class AccountPanel extends javax.swing.JPanel implements EventListener{
jScrollPane1 = new javax.swing.JScrollPane();
assetTable = new javax.swing.JTable();
jLabel1 = new javax.swing.JLabel();
finalbalance = new javax.swing.JLabel();
assetTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null},
{null, null}
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Asset", "Ammount"
"Asset", "Ammount", "Margin", "SL"
}
) {
Class[] types = new Class [] {
java.lang.String.class, java.lang.String.class
java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
};
boolean[] canEdit = new boolean [] {
false, false
false, false, false, false
};
public Class getColumnClass(int columnIndex) {
@ -108,21 +127,39 @@ public class AccountPanel extends javax.swing.JPanel implements EventListener{
});
jScrollPane1.setViewportView(assetTable);
jLabel1.setText("Final:");
finalbalance.setText("jLabel2");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(finalbalance)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 214, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(32, 32, 32)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(finalbalance))
.addGap(0, 32, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTable assetTable;
private javax.swing.JLabel finalbalance;
private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables

View 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>

View 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.AccountImpl;
/**
*
* @author 7u83 <7u83@mail.ru>
*/
public class StatusPanel extends javax.swing.JPanel {
/**
* Creates new form StatusPanel
*/
public StatusPanel() {
initComponents();
}
public StatusPanel(AccountImpl account) {
this();
setAccount(account);
}
private AccountImpl account;
public void setAccount(AccountImpl 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
}

View File

@ -0,0 +1,10 @@
{
"version": 0.2,
"assets": [
{
"type": "opensesim.sesim.assets.StockAsset",
"symbol": "MSFT",
"name": "Microsoft"
}
]
}

View File

@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.Assets;
package opensesim.sesim.assets;
import opensesim.world.AbstractAsset;
import opensesim.world.GodWorld;

View File

@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.Assets;
package opensesim.sesim.assets;
import opensesim.world.AbstractAsset;
import opensesim.world.GodWorld;

View File

@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.Assets;
package opensesim.sesim.assets;
import opensesim.world.AbstractAsset;
import opensesim.world.GodWorld;

View File

@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.Assets;
package opensesim.sesim.assets;
import javax.swing.JPanel;
import opensesim.world.AbstractAsset;

View File

@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.Assets;
package opensesim.sesim.assets;
/**
*

View File

@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.Assets;
package opensesim.sesim.assets;
import opensesim.world.AbstractAsset;
import opensesim.world.GodWorld;
@ -34,9 +34,9 @@ import org.json.JSONObject;
*
* @author 7u83 <7u83@mail.ru>
*/
public class StockAssett extends AbstractAsset{
public class StockAsset extends AbstractAsset{
public StockAssett(GodWorld world, JSONObject cfg) {
public StockAsset(GodWorld world, JSONObject cfg) {
super(world, cfg);
}

View File

@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.Assets;
package opensesim.sesim.assets;
import opensesim.world.AbstractAsset;
import opensesim.world.GodWorld;

View File

@ -37,7 +37,7 @@ public abstract class AbstractTrader implements Trader {
private String name = "Unnamed";
private String status;
private World world;
protected Account account;
protected AccountImpl account;
/**
* @return the world
@ -100,7 +100,7 @@ public abstract class AbstractTrader implements Trader {
public AbstractTrader(World world, JSONObject cfg) {
this.world=world;
this.account = new Account();
this.account = new AccountImpl(world);
AssetPack pack;
pack = new AssetPack(this.world.getDefaultAssetPair().getCurrency(),1000);
@ -118,7 +118,7 @@ public abstract class AbstractTrader implements Trader {
}
@Override
public Account getAccount(){
public AccountImpl getAccount(){
return account;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 7u83 <7u83@mail.ru>
* Copyright (c) 2019, 7u83 <7u83@mail.ru>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,86 +25,24 @@
*/
package opensesim.world;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import opensesim.util.scheduler.Event;
import opensesim.util.scheduler.EventListener;
import org.json.JSONObject;
/**
* Class to hold account data of traders
*
* @author 7u83 <7u83@mail.ru>
*/
public class Account {
HashMap<AbstractAsset, Double> assets = new HashMap<>();
HashMap<AbstractAsset, Double> assets_avail = new HashMap<>();
Trader owner;
Exchange exchange = null;
public Map<AbstractAsset, Double> getAssets() {
return Collections.unmodifiableMap(assets);
}
public Map<AbstractAsset, Double> getAssetsAavail() {
return Collections.unmodifiableMap(assets_avail);
}
public Trader getOwner() {
return owner;
}
protected Account(Exchange exchange) {
this.exchange = exchange;
}
protected Account(Exchange exchange, JSONObject cfg) {
this.exchange = exchange;
}
Account() {
}
synchronized void add(AssetPack pack) {
assets.put(pack.asset, get(pack.asset) + pack.volume);
assets_avail.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);
}
public interface Account {
/**
* Get a list of assets accumulated in this account
* @return Map of assets
*/
public Map<Asset, Double> getAssets();
/**
* Get the exchange this accounts belongs to
* @return Exchange
*/
public Exchange getExchange() ;
public double get(AbstractAsset asset) {
return assets.getOrDefault(asset, 0.0);
}
public double getAvail(AbstractAsset asset) {
return assets_avail.getOrDefault(asset, 0.0);
}
public void addAvail(AbstractAsset asset, double val) {
double avail = getAvail(asset);
assets_avail.put(asset, avail+val);
}
HashSet<EventListener> listeners = new HashSet<>();
public void addListener(EventListener l){
listeners.add(l);
}
public void notfiyListeners(){
Event e = new Event() {};
for(EventListener l: listeners){
l.receive(e);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 7u83 <7u83@mail.ru>
* Copyright (c) 2019, 7u83 <7u83@mail.ru>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -23,40 +23,30 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package opensesim.sesim.interfaces;
package opensesim.world;
import java.util.Collections;
import java.util.HashMap;
import javax.swing.JPanel;
import opensesim.world.RealWorld;
import opensesim.util.idgenerator.IDGenerator;
import opensesim.util.idgenerator.Id;
import java.util.Map;
/**
*
* @author 7u83 <7u83@mail.ru>
*/
public interface Asset extends Configurable {
public abstract class AccountBase implements Account {
static HashMap<Id, Asset> assetsById = new HashMap<>();
static HashMap<String, Asset> assetsBySymbol = new HashMap<>();
static IDGenerator assetIdGenerator = new IDGenerator();
HashMap<Asset, Double> assets = new HashMap<>();
public String getSymbol();
@Override
public Map<Asset, Double> getAssets() {
return Collections.unmodifiableMap(assets);
}
public Id getID();
Exchange exchange;
public Id setID(Id id);
@Override
public Exchange getExchange() {
return exchange;
}
public JPanel getEditGui();
/**
* Indicate if this asset can act as currency
*
* @return true if currency, false no.
*/
public boolean isCurrency();
public String getTypeName();
// public Asset(Id);
}

View File

@ -0,0 +1,425 @@
/*
* Copyright (c) 2018, 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.world;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import opensesim.util.scheduler.Event;
import opensesim.util.scheduler.EventListener;
import org.json.JSONObject;
/**
* Class to hold account data of traders
*
* @author 7u83 <7u83@mail.ru>
*/
public class AccountImpl extends AccountBase {
HashMap<AbstractAsset, Double> assets_bound = new HashMap<>();
HashMap<AbstractAsset, Order> stop_loss = new HashMap<>();
Trader owner;
//public Exchange exchange = null;
private RealWorld world;
private boolean unlimited = false;
public boolean isUnlimied() {
return unlimited;
}
void setUnlimied(boolean unlimied) {
this.unlimited = unlimied;
}
private double leverage = 0.0;
public double getLeverage() {
return leverage;
}
protected void setLeverage(double leverage) {
this.leverage = leverage;
}
/* public Map<AbstractAsset, Double> getAssetsAavail() {
return Collections.unmodifiableMap(assets_bound);
}
*/
public Trader getOwner() {
return owner;
}
protected AccountImpl(World world) {
this(world, null, null);
}
protected AccountImpl(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 f = this.getFinalBalance(currency) * getLeverage() ;
System.out.printf("Debth %f - Final: %f Return margin %f\n", d,f, f-d);
return f-d;*/
if (!this.isLeveraged())
return 0.0;
return this.getFinalBalance(currency) * getLeverage() + this.getFinalBalance(currency)
- this.getAssetDebt(world.getDefaultExchange(), currency);
// + this.get(currency);
}
synchronized void add(AssetPack pack) {
assets.put(pack.asset, get(pack.asset,false) + pack.volume);
// assets_bound.put(pack.asset, getAvail(pack.asset) + pack.volume);
}
synchronized void sub(AssetPack pack) {
assets.put(pack.asset, get(pack.asset,false) - pack.volume);
// assets_bound.put(pack.asset, getAvail(pack.asset) - pack.volume);
}
public double get(AbstractAsset asset, boolean bound) {
return assets.getOrDefault(asset, 0.0)
+ (bound ? this.getBound(asset) : 0.0);
}
public double get(AbstractAsset asset) {
return get(asset, true);
}
/*public double getAvail(AbstractAsset asset) {
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_bound.getOrDefault(asset, 0.0);
}
*/
/* public void addAvail(AbstractAsset asset, double val) {
double avail = getAvail(asset);
// assets_bound.put(asset, (avail + val));
}
*/
HashSet<EventListener> listeners = new HashSet<>();
public void addListener(EventListener l) {
listeners.add(l);
}
public void notfiyListeners() {
Event e = new Event() {
};
for (EventListener l : listeners) {
l.receive(e);
}
}
public Double getFreeMargin(AbstractAsset asset) {
return 0.0;
}
public Double getAssetDebt(Exchange ex, AbstractAsset currency) {
Double result = 0.0;
boolean bound = true;
for (Asset a : assets.keySet()) {
if (a.equals(currency)) {
continue;
}
AssetPair pair = world.getAssetPair((AbstractAsset) a, currency);
if (pair == null) {
continue;
}
TradingEngine api = (TradingEngine) ex.getAPI(pair);
Double v = get((AbstractAsset) a) * api.last_quote.price;
// Double sl = this.calcStopLoss(a);
Double n = get((AbstractAsset) a);
if (n == 0.0) {
continue;
}
// System.out.printf("Asset: %s - %f %f %f\n", a.getSymbol(), n, v, sl * n);
// Double sld = v - sl * n;
result = result + Math.abs(v); // - sl * n);
// System.out.printf("Result is now %f\n", result);
}
// System.out.printf("Return Dresult %f\n", result);
return result;
}
/**
* Determine final balance of this account, as if all assets would be sold
* on exchange ex against given currency asset.
*
* @param ex Exchange to operate on
* @param currency Currency against the assets should be sold.
* @return final balance
*
*/
public Double getFinalBalance(Exchange ex, AbstractAsset currency,
boolean bound) {
Double result = 0.0; //get(currency);
for (Asset a : assets.keySet()) {
Double v;
if (a.equals(currency)) {
v = get((AbstractAsset) a, bound);
result += v;
continue;
}
AssetPair pair = world.getAssetPair((AbstractAsset) a, currency);
if (pair == null) {
continue;
}
v = get((AbstractAsset) a, bound);
if (v == 0.0) {
continue;
}
TradingEngine api = (TradingEngine) ex.getAPI(pair);
result = result + v * api.last_quote.price;
}
return result;
}
/**
* Return the amount of bound assets
*
* @param asset Asset to check
* @return amount
*/
public Double getBound(AbstractAsset asset) {
return assets_bound.getOrDefault(asset, 0.0);
}
void addBound(AbstractAsset asset, Double vol) {
assets.put(asset, get(asset, false));
assets_bound.put(asset, getBound(asset) + vol);
}
/**
* Get the final balance as if all assets would be sold ob the default
* exchange against given currency.
* {@link #getFinalBalance(opensesim.world.Exchange, opensesim.world.AbstractAsset)}
*
* @param currency Currency for final balance
* @return final balance
*/
public Double getFinalBalance(AbstractAsset currency) {
return getFinalBalance(this.getExchange(), currency, true);
}
/**
* Determine final balance
* {@link #getFinalBalance(opensesim.world.Exchange, opensesim.world.AbstractAsset) }
*
* @see DoublegetFinalBalance( Exchange ex, AbstractAsset currency)
* @return Balance
*/
public Double getFinalBalance() {
return getFinalBalance(world.getDefaultCurrency());
}
/**
*
* @param ex
* @param asset
* @param currency
* @return
*/
public Double calcStopLoss(Exchange ex, AbstractAsset asset, AbstractAsset currency) {
Double e = (get(currency,false));
for (Asset a : assets.keySet()) {
if (a.equals(asset)) {
continue;
}
AssetPair pair = world.getAssetPair((AbstractAsset) a, currency);
if (pair == null) {
continue;
}
TradingEngine api = (TradingEngine) ex.getAPI(pair);
Double v = get((AbstractAsset) a,false) * api.last_quote.price;
e = e + v;
}
this.calcMarginStopLosses(currency);
return -(double) e / (double) get(asset);
}
/**
*
* @param currency
*/
public void calcMarginStopLosses(AbstractAsset currency){
Double e = (get(currency,false));
int n = 0;
for (Asset a : assets.keySet()){
AssetPair pair = world.getAssetPair(a, currency);
if (pair == null)
continue;
TradingEngine api = (TradingEngine) exchange.getAPI(pair);
Double v = get((AbstractAsset) a,false) * api.last_quote.price;
e = e + v;
n++;
}
for (Asset a : assets.keySet()){
AssetPair pair = world.getAssetPair(a, currency);
if (pair == null)
continue;
TradingEngine api = (TradingEngine) exchange.getAPI(pair);
Double v = get((AbstractAsset) a,false) * api.last_quote.price;
Double sl = -(double) (e-v) / (double) get((AbstractAsset) a);
sl = api.last_quote.price - (api.last_quote.price - sl)/(double)n;
System.out.printf("(%d)ASS SL for %s: %f\n",n, a.getSymbol(), sl);
}
}
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() {
return world;
}
private boolean isLeveraged() {
return getLeverage() > 0.0;
}
/**
* Bind asset which will be locked in an order.
*
* @param pair
* @param volume
* @param limit
* @return true if asset could be bound, false if assets couldn't be bound
*/
boolean bind(AssetPair pair, double volume, double limit) {
// Bind asset and currecy - optimistic
this.addBound(pair.getAsset(), volume);
this.addBound(pair.getCurrency(), -(volume * limit));
if (this.isUnlimied()) {
// in case it is an unlimited account we can return
// true without further checks
return true;
}
// checks for leveraged account
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
if (get(pair.getAsset()) >= 0) {
return true;
}
// unbind and return false
this.addBound(pair.getAsset(), -volume);
this.addBound(pair.getCurrency(), (volume * limit));
return false;
}
// Check if enough money is available to cover the
// entiere volume to by
if (get(pair.getCurrency()) >= 0) {
return true;
}
// unbind and return false
this.addBound(pair.getAsset(), -volume);
this.addBound(pair.getCurrency(), (volume * limit));
return false;
}
// we are dealing here with a leveraged account
Double margin = this.getMargin(pair.getCurrency());
if (margin >= 0) {
return true;
}
// Unbind asset and currency
this.addBound(pair.getAsset(), -volume);
this.addBound(pair.getCurrency(), (volume * limit));
return false;
}
}

View File

@ -50,7 +50,7 @@ public interface Asset {
public String getSymbol();
/**
* Determine if this asset can be used as currency
* Determine if this asset can be used as currency.
* @return true if asset can act as currency, false if not.
*/
public boolean isCurrency();

View File

@ -51,12 +51,12 @@ public class AssetPair {
return buildSymbol(asset.getSymbol(),currency.getSymbol());
}
public AssetPair(AbstractAsset asset, AbstractAsset currency) {
AssetPair(AbstractAsset asset, AbstractAsset currency) {
this.asset = asset;
this.currency = currency;
}
public AssetPair(World world, String asset, String currency){
AssetPair(World world, String asset, String currency){
this.asset = world.getAssetBySymbol(asset);
this.currency = world.getAssetBySymbol(currency);
}

View File

@ -41,10 +41,10 @@ public class Exchange implements Configurable, GetJson {
private String name;
private String symbol;
public void setName(String name) {
/* public void setName(String name) {
this.name = name;
}
*/
private final HashMap<AssetPair, TradingAPI> asset_pairs = new HashMap<>();
Exchange(GodWorld world, String symbol) {
@ -68,15 +68,15 @@ public class Exchange implements Configurable, GetJson {
return symbol;
}
private HashSet<Account> accounts = new HashSet<>();
private HashSet<AccountImpl> accounts = new HashSet<>();
Account createAccount() {
Account a = new Account(this);
AccountImpl createAccount() {
AccountImpl a = new AccountImpl(this.world);
accounts.add(a);
return a;
}
public Order createOrder(Account account, AssetPair pair, Order.Type type, double volume, double limit) {
public Order createOrder(AccountImpl account, AssetPair pair, Order.Type type, double volume, double limit) {
// Order o = new Order(world,account,assetpair,type,volume,limit);
return null;

View File

@ -25,6 +25,8 @@
*/
package opensesim.world;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
@ -32,6 +34,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -62,6 +65,11 @@ public class GodWorld implements GetJson, World {
return scheduler.currentTimeMillis();
}
@Override
public AbstractAsset getDefaultCurrency() {
return getDefaultAssetPair().getCurrency();
}
public static final class JKEYS {
public static final String ASSETS = "assets";
@ -69,8 +77,12 @@ public class GodWorld implements GetJson, World {
public static final String ASSET_SYMBOL = "symbol";
public static final String ASSET_TYPE = "type";
public static final String VERSION = "version";
}
public static double VERSION = 0.2;
/* HashSet<AbstractAsset> assetsById = new HashSet<>();
HashMap<String, AbstractAsset> assetsBySymbol = new HashMap<>();
@ -86,9 +98,25 @@ public class GodWorld implements GetJson, World {
*/
public GodWorld(JSONObject cfg) {
init(cfg, false);
}
public GodWorld(InputStream is) throws IOException{
String s = new Scanner(is, "UTF-8").useDelimiter("\\A").next();
JSONObject cfg = new JSONObject(s);
Double version = cfg.getDouble(GodWorld.JKEYS.VERSION);
if (version != GodWorld.VERSION) {
throw new IOException("File has wrong version.");
}
init(cfg,false);
}
private void init(JSONObject cfg, boolean mt) {
// this.scheduler = new Scheduler();
// this.scheduler.start();
putJson(cfg);
}
public Scheduler getScheduler() {
return scheduler;
}
@ -101,11 +129,6 @@ public class GodWorld implements GetJson, World {
this(new JSONObject("{}"));
}
private void init(JSONObject cfg, boolean mt) {
this.scheduler = new Scheduler();
this.scheduler.start();
putJson(cfg);
}
private void putJson(JSONObject cfg) {
// Read assets
@ -165,11 +188,19 @@ public class GodWorld implements GetJson, World {
return cfg;
}
/**
* Create an asset from a JSON object
*
* @param cfg the JSON object to create the asset from
* @return the created asset
* @throws SeSimException
*/
public AbstractAsset createAsset(JSONObject cfg) throws SeSimException {
AbstractAsset a;
String class_name;
Class<AbstractAsset> cls;
// get asset name
try {
class_name = cfg.getString(JKEYS.ASSET_TYPE);
} catch (JSONException jex) {
@ -177,11 +208,14 @@ public class GodWorld implements GetJson, World {
return null;
}
// create class from name
try {
cls = (Class<AbstractAsset>) Class.forName(class_name);
a = cls.getConstructor(GodWorld.class, JSONObject.class).newInstance(this, cfg);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(GodWorld.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException
| InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException ex) {
Logger.getLogger(GodWorld.class.getName()).log(Level.SEVERE, class_name, ex);
return null;
}
@ -256,6 +290,9 @@ public class GodWorld implements GetJson, World {
}
public void add(AssetPair pair) {
if (pair.getAsset()==null || pair.getCurrency()==null){
return;
}
asset_pairs.put(pair.getSymbol(), pair);
if (default_asset_pair == null) {
default_asset_pair = pair;
@ -271,6 +308,11 @@ public class GodWorld implements GetJson, World {
public AssetPair getDefaultAssetPair() {
return default_asset_pair;
}
public AssetPair getAssetPair(Asset asset, Asset currency){
String s = AssetPair.buildSymbol(asset.getSymbol(), currency.getSymbol());
return asset_pairs.getOrDefault(s, null);
}
/* public AbstractAsset createAsset(long key, JSONObject cfg) throws SeSimException{

View File

@ -69,9 +69,21 @@ public class Order implements Comparable<Order> {
* Definition of order status
*/
public static enum Status {
OPEN, PARTIALLY_EXECUTED, CLOSED, CANCELED
OPEN, PARTIALLY_EXECUTED, CLOSED, CANCELED, ERROR
}
String message="";
public String getMessage() {
return message;
}
private void setMessage(String message) {
this.message = message;
}
/**
* Definition of order types
*/
@ -94,12 +106,12 @@ public class Order implements Comparable<Order> {
protected final Id id;
protected final long created;
protected final Account account;
protected final AccountImpl account;
double cost;
GodWorld world;
Order(TradingEngine engine, Account account, Type type,
Order(TradingEngine engine, AccountImpl account, Type type,
double volume, double limit, Addition addition) {
// Assign volume and initial volume
@ -120,7 +132,7 @@ public class Order implements Comparable<Order> {
this.addition = addition;
}
Order(opensesim.world.TradingEngine engine, Account account, Type type,
Order(opensesim.world.TradingEngine engine, AccountImpl account, Type type,
double volume, double limit) {
this(engine, account, type, volume, limit, Addition.NONE);
}
@ -161,7 +173,7 @@ public class Order implements Comparable<Order> {
return cost / e;
}
public Account getAccount() {
public AccountImpl getAccount() {
return account;
}

View File

@ -85,4 +85,14 @@ public class RealWorld implements World {
return godworld.getDefaultAssetPair();
}
@Override
public AssetPair getAssetPair(Asset asset, Asset currency) {
return godworld.getAssetPair(asset, currency);
}
@Override
public AbstractAsset getDefaultCurrency() {
return godworld.getDefaultCurrency();
}
}

View File

@ -49,7 +49,7 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
if (cfg == null) {
return;
}
}
public SimpleTrader() {
@ -74,8 +74,8 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
return 0;
}
public Account account_s, account_b;
public AccountImpl account_b, account_1;
@Override
public void start() {
setVerbose(true);
@ -92,47 +92,30 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
setStatus("Stopped.");
return;
}
AbstractAsset c,a;
AbstractAsset c, a;
AssetPair p = getWorld().getDefaultAssetPair();
account_s = new Account();
account_b = new Account();
account_b = new AccountImpl(getWorld());
account_1 = new AccountImpl(getWorld());
AssetPack pack;
pack = new AssetPack(p.getAsset(),200);
account_s.add(pack);
pack = new AssetPack(p.getCurrency(),10000);
// pack = new AssetPack(p.getAsset(), 0);
// account_b.add(pack);
pack = new AssetPack(p.getCurrency(), 1000);
account_b.add(pack);
ex = getWorld().getDefaultExchange();
api = ex.getAPI(p);
account_b.setLeverage(9);
Order oa = api.createOrder(account_b, Order.Type.BUYLIMIT, 200, 100);
Order ob = api.createOrder(account_s, Order.Type.SELLLIMIT, 200,200);
pack = new AssetPack(p.getCurrency(), 10000);
account_1.add(pack);
account_1.setLeverage(0.0);
account_1.setUnlimied(true);
// Order oa = api.createOrder(account_b, Order.Type.BUYLIMIT, 100, 10.0);
// Order ob = api.createOrder(account_b, Order.Type.BUYLIMIT, 100, 9.0);
// Order oc = api.createOrder(account_b, Order.Type.BUYLIMIT, 100, 8.0);
// Order o2 = api.createOrder(account_s, Order.Type.SELLLIMIT, 300, 1.0);
//Order ou = api.createOrder(account_b, Order.Type.BUYLIMIT, 30, 10.0);
// Order o1 = api.createOrder(account, Order.Type.SELLLIMIT, 250, 278);
long delay = (long) (1000.0f * getWorld().randNextFloat(3.0f, 12.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);
getWorld().schedule(this, delay);
// long delay = (long) (getRandom(initial_delay[0], initial_delay[1]) * 1000);
// setStatus("Inital delay: %d", delay);
@ -143,9 +126,6 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
double limit = 253.871239;
@Override
public long receive(Event task) {
// System.out.printf("Here we are !!! %f\n", getWorld().randNextFloat(12f, 27f));
@ -153,16 +133,23 @@ public class SimpleTrader extends AbstractTrader implements EventListener {
long diff = getWorld().currentTimeMillis() - last_time;
last_time = getWorld().currentTimeMillis();
System.out.printf("Here we are: %d - [%d]\n", Thread.currentThread().getId(), diff);
getWorld().schedule(this, 1000);
AssetPair p = getWorld().getDefaultAssetPair();
AssetPair p = getWorld().getDefaultAssetPair();
ex = getWorld().getDefaultExchange();
api = ex.getAPI(p);
Order o = api.createOrder(account, Order.Type.BUY, 112.987123, limit);
limit += 12;
api = ex.getAPI(p);
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 obm = mapi.createOrder(account_b, Order.Type.BUYLIMIT, 20, 100);
Order oba = api.createOrder(account_1, Order.Type.SELLLIMIT, 20, 100);
Order obam = mapi.createOrder(account_1, Order.Type.SELLLIMIT, 20, 100);
return -1;
}

View File

@ -39,6 +39,6 @@ public interface Trader {
*
* @return
*/
public Account getAccount();
public AccountImpl getAccount();
}

View File

@ -36,7 +36,7 @@ public interface TradingAPI {
public void addOrderBookListener(EventListener listener);
public Order createOrder(Account account, Order.Type type, double volume, double limit);
public Order createOrder(AccountImpl account, Order.Type type, double volume, double limit);
public Set getBidBook();
@ -51,5 +51,7 @@ public interface TradingAPI {
public AssetPair getAssetPair();
public Set<Quote> getQuoteHistory();
public Quote getLastQuote();
}

View File

@ -42,17 +42,17 @@ import opensesim.util.scheduler.FiringEvent;
*/
class TradingEngine implements TradingAPI {
private final Exchange outer;
private final Exchange exchange;
/**
* Construct a trading engine for an asset pair
*
* @param pair The AssetPair object to create the trading engine for
* @param outer Outer class - points to an Exchange object thins trading
* @param exchange Outer class - points to an Exchange object this trading
* engine belongs to.
*/
TradingEngine(AssetPair pair, final Exchange outer) {
this.outer = outer;
TradingEngine(AssetPair pair, final Exchange exchange) {
this.exchange = exchange;
assetpair = pair;
reset();
}
@ -117,7 +117,7 @@ class TradingEngine implements TradingAPI {
boolean compact_history = false;
boolean compact_last = true;
private void transferMoneyAndShares(Account src, Account dst, double money, double shares) {
private void transferMoneyAndShares(AccountImpl src, AccountImpl dst, double money, double shares) {
// src.money -= money;
AssetPack pack;
@ -208,7 +208,7 @@ class TradingEngine implements TradingAPI {
double volume = b.volume >= a.volume ? a.volume : b.volume;
double avdiff = b.limit - price * volume;
b.account.addAvail(assetpair.getCurrency(), avdiff);
// b.account.addAvail(assetpair.getCurrency(), avdiff);
finishTrade(b, a, price, volume);
volume_total += volume;
@ -219,8 +219,8 @@ class TradingEngine implements TradingAPI {
q = new Quote(quote_id_generator.getNext());
q.price = price;
q.volume = volume;
q.time = outer.world.currentTimeMillis();
q.type = type;
q.time = exchange.world.currentTimeMillis();
q.type = type;
addQuoteToHistory(q);
}
@ -250,7 +250,6 @@ class TradingEngine implements TradingAPI {
this.checkSLOrders(price);
}
*/
//
// Match limited orders against limited orders
//
@ -288,16 +287,30 @@ class TradingEngine implements TradingAPI {
// Update available currency for the buyer.
// For sellers there is no need to update.
double avdiff = b.limit * volume - price * volume;
b.account.addAvail(assetpair.getCurrency(), avdiff);
double avdiff;
// b.account.addAvail(assetpair.getCurrency(), avdiff);
avdiff = b.limit * volume - price * volume;
// Unbind
double bound = b.account.getBound(assetpair.getCurrency());
double addbound = volume*b.limit;
b.account.addBound(assetpair.getCurrency(), volume*b.limit);
b.account.addBound(assetpair.getAsset(), -volume);
a.account.addBound(assetpair.getCurrency(), -volume*b.limit);
a.account.addBound(assetpair.getAsset(), volume);
// b.account.addMarginAvail(assetpair.getCurrency(), avdiff/b.account.getLeverage());
finishTrade(b, a, price, volume);
if (!compact_history) {
q = new Quote(quote_id_generator.getNext());
q.price = price;
q.volume = volume;
q.time = outer.world.currentTimeMillis();
q.time = exchange.world.currentTimeMillis();
q.type = type;
addQuoteToHistory(q);
}
@ -317,7 +330,7 @@ class TradingEngine implements TradingAPI {
qc = new Quote(quote_id_generator.getNext());
qc.price = money_total / volume_total;
qc.volume = volume_total;
qc.time = outer.world.currentTimeMillis();
qc.time = exchange.world.currentTimeMillis();
if (compact_history) {
addQuoteToHistory(qc);
@ -362,7 +375,7 @@ class TradingEngine implements TradingAPI {
return b.limit;
}
// Last price is grater ask, so return the current ask
// Last price is greater than ask, so return the current ask
if (last_quote.price > a.limit) {
return a.limit;
}
@ -409,7 +422,7 @@ class TradingEngine implements TradingAPI {
}
@Override
public Order createOrder(Account account, Order.Type type,
public Order createOrder(AccountImpl account, Order.Type type,
double volume, double limit) {
Order o;
@ -430,17 +443,23 @@ class TradingEngine implements TradingAPI {
switch (type) {
case BUYLIMIT: {
// verfify available currency for a buy limit order
AbstractAsset currency = this.assetpair.getCurrency();
Double avail = account.getAvail(currency);
// return if not enough money is available
if (avail < v * l) {
if (!account.bind(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;
// 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;
break;
@ -450,15 +469,16 @@ class TradingEngine implements TradingAPI {
// For an unlimited by order there is nothing to check
// other than currency is > 0.0
AbstractAsset currency = this.assetpair.getCurrency();
Double avail = account.getAvail(currency);
if (avail <= 0.0) {
return null;
}
// Double avail = account.getAvail(currency);
Double avail = 1000.0;
// if (avail <= 0.0) {
// return null;
// }
// 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;
@ -468,17 +488,12 @@ class TradingEngine implements TradingAPI {
case SELLLIMIT:
case SELL: {
// verfiy sell limit
AbstractAsset asset = this.assetpair.getAsset();
Double avail = account.getAvail(asset);
if (avail < v) {
// not enough items of asset (shares) available
if (!account.bind(assetpair, -volume, limit)) {
System.out.printf("Not enough funds\n");
return null;
}
account.assets_avail
.put(asset, avail - v);
}
order_limit = l;
break;
@ -497,16 +512,20 @@ class TradingEngine implements TradingAPI {
}
}
executeOrders();
executeOrders();
// last_quote.price = 90; //75-12.5;
for (FiringEvent e : book_listener) {
e.fire();
}
account.notfiyListeners();
return o;
}
HashSet<FiringEvent> book_listener = new HashSet<>();
HashSet<FiringEvent> book_listener
= new HashSet<>();
@Override
public void addOrderBookListener(EventListener listener) {
@ -515,18 +534,25 @@ class TradingEngine implements TradingAPI {
}
@Override
public Set getOrderBook(Order.Type type) {
public Set
getOrderBook(Order.Type type
) {
switch (type) {
case BUYLIMIT:
case BUY:
return Collections.unmodifiableSet(bidbook);
return Collections
.unmodifiableSet(bidbook
);
case SELLLIMIT:
case SELL:
return Collections.unmodifiableSet(askbook);
return Collections
.unmodifiableSet(askbook
);
}
return null;
}
@Override
@ -547,9 +573,12 @@ class TradingEngine implements TradingAPI {
@Override
public Set<Quote> getQuoteHistory() {
return Collections
.unmodifiableSet(quote_history
);
return Collections.unmodifiableSet(quote_history);
}
@Override
public Quote getLastQuote() {
return this.last_quote;
}
}

View File

@ -30,19 +30,29 @@ import java.util.Collection;
import opensesim.util.scheduler.EventListener;
/**
*
* The interface to the world. Used by traders. And others.
* @author 7u83 <7u83@mail.ru>
*/
public interface World {
/**
* Get available assets in this world.
* @return Collection of {@link opensesim.world.Asset}s
*/
public Collection<AbstractAsset> getAssetCollection();
/**
* Return asset by symbol
* @param symbol symbol to find
* @return asset
*/
public AbstractAsset getAssetBySymbol(String symbol);
Collection<Exchange> getExchangeCollection();
public Exchange getDefaultExchange();
public AssetPair getDefaultAssetPair();
public AbstractAsset getDefaultCurrency();
Collection<Trader> getTradersCollection();
@ -51,4 +61,6 @@ public interface World {
public float randNextFloat(float min, float max);
public long currentTimeMillis();
public AssetPair getAssetPair(Asset asset, Asset currency);
}

View File

@ -26,8 +26,8 @@
package opensesim.world;
import java.util.Map;
import opensesim.sesim.Assets.CurrencyAsset;
import opensesim.sesim.Assets.DummyAsset;
import opensesim.sesim.assets.CurrencyAsset;
import opensesim.sesim.assets.DummyAsset;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@ -66,7 +66,7 @@ public class AccountTest {
/* @Test
public void testGetAssets() {
System.out.println("getAssets");
Account instance = new Account();
AccountImpl instance = new AccountImpl();
Map<AbstractAsset, Double> expResult = null;
Map<AbstractAsset, Double> result = instance.getAssets();
assertEquals(expResult, result);
@ -75,12 +75,12 @@ public class AccountTest {
}
*/
/**
* Test of getOwner method, of class Account.
* Test of getOwner method, of class AccountImpl.
*/
@Test
public void testGetOwner() {
System.out.println("getOwner");
Account instance = new Account();
AccountImpl instance = new AccountImpl();
Trader expResult = null;
Trader result = instance.getOwner();
assertEquals(expResult, result);
@ -89,7 +89,7 @@ public class AccountTest {
}
/**
* Test of add method, of class Account.
* Test of add method, of class AccountImpl.
*/
@Test
public void testAdd() {
@ -100,7 +100,7 @@ public class AccountTest {
Double expResult = 123.0;
AssetPack pack = new AssetPack(c, expResult);
Account account = new Account();
AccountImpl account = new AccountImpl();
account.add(pack);
Double result;

View File

@ -89,11 +89,11 @@ public class ExchangeTest {
AssetPair ap = new AssetPair(world,"EUR","AAPL");
Exchange instance = new Exchange(null, (JSONObject) null);
Account expResult = null;
AccountImpl expResult = null;
Account result = instance.createAccount();
AccountImpl result = instance.createAccount();
// assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
// fail("The test case is a prototype.");

View File

@ -78,7 +78,7 @@ public class TradingAPITest {
@Test
public void testCreateOrder() {
System.out.println("createOrder");
Account account = null;
AccountImpl account = null;
Order.Type type = null;
double volume = 0.0;
double limit = 0.0;
@ -152,7 +152,7 @@ public class TradingAPITest {
public void addOrderBookListener(EventListener listener) {
}
public Order createOrder(Account account, Order.Type type, double volume, double limit) {
public Order createOrder(AccountImpl account, Order.Type type, double volume, double limit) {
return null;
}

View File

@ -26,7 +26,7 @@
package opensesim.world;
import java.util.Set;
import opensesim.sesim.Assets.CurrencyAsset;
import opensesim.sesim.assets.CurrencyAsset;
import opensesim.util.scheduler.EventListener;
import org.junit.After;
import org.junit.AfterClass;
@ -110,7 +110,7 @@ public class TradingEngineTest {
// AbstractAsset currency = gdworld.createAsset(cfg);
Account account = new Account();
AccountImpl account = new AccountImpl();
Order.Type type = null;