Skip to content

Commit

Permalink
finish up ccxt
Browse files Browse the repository at this point in the history
  • Loading branch information
Etienne Gobeli committed Jan 18, 2018
1 parent 941e8f1 commit af4ae9b
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 156 deletions.
55 changes: 55 additions & 0 deletions src/renderer/components/Chart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<template>
<vue-chart
:rows="$store.state.marketData.map(x => [null, x.last, x.buy, x.sell])"
:columns="[{ type: 'string', label: '' },{ type: 'number', label: 'Last' }, { type: 'number', label: 'Buy' }, { type: 'number', label: 'Sell' }]"
:options="chartOptions"
></vue-chart>
</template>

<script>
importhandleError } from '../helper';
export default {
name: 'pnd-chart',
props: ['strategy', 'pollingTimeout', 'market'],
data: () => ({
marketData: [],
tickerInterval: null,
chartOptions: {
annotations: {
duration: 1000,
easing: 'out',
},
hAxis: {
title: 'time',
},
vAxis: {
title: 'price',
},
},
}),
created() {
this.createTicker(this.pollingTimeout);
},
watch: {
pollingTimeout(newVal, oldVal) {
this.createTicker(newVal);
}
},
methods: {
createTicker(pollingTimeout) {
clearInterval(this.tickerInterval);
this.tickerInterval = setInterval(this.updateTicker.bind(this), pollingTimeout);
this.updateTicker();
},
updateTicker() {
this.$store.state.exchange.fetchTicker(this.market).catch(handleError(this))
.then(tick =>
this.$store.commit('ADD_MARKETDATA', {last: tick.last,
buy: this.$store.state.running ? this.$store.state.settings.buy : null,
sell: this.$store.state.running ? this.$store.state.settings.sell : null
})
);
}
}
}
</script>
16 changes: 10 additions & 6 deletions src/renderer/components/ExecuteModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@
:visible.sync="open"
size="tiny"
:before-close="() => $emit('close-modal')">
<h3>Trade {{market}}</h3>
<h3>Trade {{market}} ({{lastPrice}})</h3>
<p>Buy: <strong>{{quantity}} {{market}}</strong> at <strong>{{bid}}</strong></p>
<p>Sell at <strong>{{ask}}</strong></p>
<el-button type="primary" @click="submit()">Ok</el-button>
</el-dialog>

</template>
<script>
import { mapGetters } from 'vuex';
import { handleError } from '../helper';
export default {
name: 'execute-modal',
props: ['open', 'strategy', 'market', 'lastPrice'],
name: 'pnd-execute-modal',
props: ['open', 'strategy', 'market'],
watch: {
open() {
this.update();
Expand All @@ -29,17 +31,20 @@
}
},
computed: {
...mapGetters([
'lastPrice',
]),
rateBuy() {
return 1 + (this.strategy.buyAt / 100);
},
rateSell() {
return 1 + (this.strategy.sellAt / 100);
},
bid() {
return this.lastPrice && this.lastPrice.last * this.rateBuy;
return this.lastPrice && this.lastPrice * this.rateBuy;
},
ask() {
return this.lastPrice && this.lastPrice.last * this.rateSell;
return this.lastPrice && this.lastPrice * this.rateSell;
},
quantity() {
if (this.lastPrice && this.strategy) {
Expand Down Expand Up @@ -71,7 +76,6 @@
});
this.$bus.$emit('update');
this.$emit('close-modal');
console.log(buyOrder, s);
this.$store.commit('SET_RUNNING', { running: true, settings: { buy: this.bid, sell: this.ask, quantity: this.quantity, buyOrder, sellOrder: s } });
})
.catch(handleError(this));
Expand Down
118 changes: 35 additions & 83 deletions src/renderer/components/Main.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="container" style="margin-top: 1rem;">
<execute-modal :lastPrice="lastPrice" :market="selectedMarket" :strategy="strategy" :open="executeModalShown" @close-modal="executeModalShown = false"></execute-modal>
<pnd-execute-modal :market="selectedMarket" :strategy="strategy" :open="executeModalShown" @close-modal="executeModalShown = false"></pnd-execute-modal>

<el-dialog
title="Use Strategy"
Expand All @@ -25,7 +25,7 @@
<div slot="header">
<h3>Polling Timeout (MS)</h3>
</div>
<el-input-number style="width: 100%" v-model="pollTimeout" @change="updateGui()"></el-input-number>
<el-input-number style="width: 100%" v-model="pollingTimeout" @change="updateGui()"></el-input-number>
</el-card>
</el-col>
</el-row>
Expand All @@ -35,7 +35,7 @@
<div slot="header" class="clearfix">
<h3>Strategy</h3>
</div>
<strategy-form :strategy-model="strategy" @strategy-changed="submitStrategy"></strategy-form>
<pnd-strategy-form :strategy-model="strategy"></pnd-strategy-form>
<el-button style="float: right; margin-bottom: 20px" type="primary" v-if="!$store.state.running" @click="useStrategy">Use</el-button>
<el-button-group style="float: right; margin-bottom: 20px" v-if="$store.state.running">
<el-button type="danger" @click="cancel(false)">Cancel</el-button>
Expand All @@ -48,29 +48,17 @@
<div slot="header" class="clearfix">
<h3>{{market}}</h3>
</div>
<vue-chart
:rows="marketData.map(x => [null, x.last, x.buy, x.sell])"
:columns="[{ type: 'string', label: '' },{ type: 'number', label: 'Last' }, { type: 'number', label: 'Buy' }, { type: 'number', label: 'Sell' }]"
:options="chartOptions"
></vue-chart>
<pnd-chart :pollingTimeout="pollingTimeout" :strategy="running ? strategy : null" :market="selectedMarket"></pnd-chart>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-card>
<div slot="header" class="clearfix">
<h3>Open Orders</h3>
</div>
<orders :orders="openOrders"></orders>
</el-card>
</el-col>
<el-col :span="12">
<el-col>
<el-card>
<div slot="header" class="clearfix">
<h3>Order History</h3>
<h3>Orders</h3>
</div>
<orders :orders="orderHistory"></orders>
<pnd-orders :orders="orders"></pnd-orders>
</el-card>
</el-col>
</el-row>
Expand All @@ -79,13 +67,14 @@
</template>

<script>
import { handleResponse } from '../helper';
importgetApiKey, getApiSecret, setApiKey, setApiSecret, storePrefix, initExchange, handleError } from '../helper';
import { mapGetters } from 'vuex';
import {setApiKey, setApiSecret, storePrefix, initExchange, handleError } from '../helper';
export default {
data: () => ({
// polling
pollTimeout: 5000,
pollingTimeout: 5000,
// market
market: '',
markets: [],
Expand All @@ -98,29 +87,17 @@
},
strategyModalShown: false,
running: false,
// chart
marketData: [],
chartStrategy: this.strategies ? this.strategies[0] : {},
tickerInterval: null,
lastPrice: null,
chartOptions: {
annotations: {
duration: 1000,
easing: 'out',
},
hAxis: {
title: 'time',
},
vAxis: {
title: 'price',
},
},
// orders
executeModalShown: false,
openOrders: [],
orderHistory: []
orders: []
}),
computed: {
...mapGetters([
'lastPrice',
])
},
created() {
this.initialize();
this.$bus.$on('update', _ => this.updateGui(null));
Expand All @@ -146,41 +123,25 @@
this.updateGui(localStorage.getItem(`${storePrefix}CURRENCY`));
},
getTicker() {
this.$store.state.exchange.fetchTicker(this.selectedMarket).catch(handleError(this))
.then(tick => {
this.lastPrice = tick;
this.marketData.push({last: tick.last,
buy: this.$store.state.running ? this.$store.state.settings.buy : null,
sell: this.$store.state.running ? this.$store.state.settings.sell : null
});
if (this.marketData.length > 100) {
this.marketData.splice(0, 1);
}
});
},
updateGui(market) {
if (!!market === true) {
this.marketData = [];
this.$store.commit('CLEAR_MARKETDATA');
localStorage.setItem(`${storePrefix}CURRENCY`, market);
this.market = market;
this.selectedMarket = market;
clearInterval(this.tickerInterval);
this.getTicker();
this.tickerInterval = setInterval(this.getTicker.bind(this), this.pollTimeout);
}
if (!this.market) {
return
if (this.market) {
this.fetchOrders();
}
},
fetchOrders() {
if (this.$store.state.exchange.hasFetchOrders) {
this.$store.state.exchange.fetchOrders(this.market).catch(handleError(this))
this.$store.state.exchange.fetchOrders(this.market)
.then(orders => {
this.orderHistory = orders.filter(o => o.status === 'closed');
console.log(orders)
this.openOrders = orders.filter(o => o.status === 'open');
});
this.orders = orders;
}).catch(handleError(this));
} else {
this.$message({ type: 'error', message: 'Fetch Orders is not supportet by ' + this.$store.state.exchange.id })
}
Expand All @@ -191,21 +152,14 @@
cb([...new Set(markets)].map(m => ({ value: m })));
},
submitStrategy(value) {
localStorage.setItem(`${storePrefix}STRATEGY`, JSON.stringify(value));
},
deleteStrategy(strategy) {
this.strategies = this.strategies.filter(s => s.uid !== strategy.uid)
},
useStrategy() {
if (this.strategy && this.strategy.volume > 0 && this.strategy.buyAt > 0 && this.strategy.sellAt > 0) {
if (this.strategy && this.strategy.volume > 0 && this.strategy.buyAt >= 0 && this.strategy.sellAt > 0) {
this.executeModalShown = true;
} else {
this.$message({ message: 'Strategy is invalid', type: 'error' });
}
},
cancelOrder(id) {
this.$store.state.exchange.fetchOrder(this.$store.state.settings.buyOrder.id).then(o => {
if (o.status === 'open') {
Expand All @@ -214,26 +168,24 @@
message: 'Order cancelled',
type: 'success',
})
)
).then(() => this.$bus.$emit('update'))
}
})
}).catch(handleError(this))
},
cancel(sell) {
this.$store.commit('SET_RUNNING', { running: false });
this.cancelOrder(this.$store.state.settings.buyOrder.id);
this.cancelOrder(this.$store.state.settings.sellOrder.id);
if (sell) {
const rate = this.marketData[this.marketData.length - 1].last;
this.$store.state.exchange.createLimitSellOrder(this.selectedMarket, this.$store.state.settings.quantity, rate)
this.$store.state.exchange.createLimitSellOrder(this.selectedMarket, this.$store.state.settings.quantity, this.lastPrice)
.catch(handleError(this))
.then(res => {
.then(res =>
this.$message({
message: 'Sell-Order placed successfully',
type: 'success',
});
})
})
).then(() => this.$bus.$emit('update'));
}
}
},
Expand Down
22 changes: 13 additions & 9 deletions src/renderer/components/Orders.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,31 @@
<div>
<div class="messages">
<el-row class="message" :gutter="10">
<el-col :span="8"><b>Type</b></el-col>
<el-col :span="8"><b>Amount</b></el-col>
<el-col :span="8"><b>Rate</b></el-col>
<el-col :span="6"><b>Type</b></el-col>
<el-col :span="6"><b>Amount</b></el-col>
<el-col :span="6"><b>Rate</b></el-col>
<el-col :span="6"><b>Status</b></el-col>
</el-row>
<el-row v-for="order in orders.slice(0,5)" class="message" :gutter="10" :key="order.id">
<el-col :span="8">
{{order.type}}
<el-col :span="6">
{{order.side}}
</el-col>
<el-col :span="8">
<el-col :span="6">
{{order.amount}}
</el-col>
<el-col :span="8">
{{order.average}}
<el-col :span="6">
{{order.price}}
</el-col>
<el-col :span="6">
{{order.status}}
</el-col>
</el-row>
</div>
</div>
</template>
<script>
export default {
name: 'orders',
name: 'pnd-orders',
props: ['title', 'orders']
}
</script>
Expand Down
8 changes: 5 additions & 3 deletions src/renderer/components/StrategyForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@
</el-form>
</template>
<script>
import { storePrefix } from '../helper';
export default {
name: 'strategy-form',
name: 'pnd-strategy-form',
props: ['strategyModel'],
watch: {
strategyModel: {
handler(newVal) {
this.$emit('strategy-changed', newVal)
localStorage.setItem(`${storePrefix}STRATEGY`, JSON.stringify(newVal));
},
deep: true
}
}
}
</script>
</script>
Loading

0 comments on commit af4ae9b

Please sign in to comment.