-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pipes - Sara Frandsen - Ada Trader #29
base: master
Are you sure you want to change the base?
Changes from all commits
00cfe83
f0e9047
e6b48a5
fa97c21
19c25e3
c34dd5d
d423c4a
9fdef1a
2a50327
3b08c76
437fa43
1d24a55
d7e129e
98c6824
0ae260e
8c44ede
9e7e144
4d29dbd
44fb593
c9c6eb9
25d1124
f5226b3
df84801
2e24458
6cfb3df
87a37ab
1a2dccf
eefb9ae
966e4e2
13a57dd
8ed6409
20a67e2
0237a41
f79d84a
beddb76
23fb6a2
dc8777f
7d64b5f
a0c2540
869c6a1
9f2c2ef
acc00e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import Order from 'models/order'; | ||
import Quote from 'models/quote'; | ||
|
||
describe('Order spec', () => { | ||
let order; | ||
beforeEach(() => { | ||
order = new Order({ | ||
symbol: 'HELLO', | ||
price: 100.00, | ||
}); | ||
}); | ||
|
||
describe('validate', () => { | ||
it('validates there is a target price', () => { | ||
const prices = ['', NaN, undefined, 0] | ||
|
||
prices.forEach((price)=> { | ||
const order = new Order({ | ||
targetPrice: price | ||
}); | ||
|
||
expect(order.isValid()).toBeFalsy(); | ||
}); | ||
}); | ||
|
||
|
||
|
||
// it('buy price is not >= to the current market price', () => { | ||
// const prices = [100,1000]; | ||
// | ||
// prices.forEach((price)=> { | ||
// const order = new Order({ | ||
// targetPrice: price, | ||
// buy: true, | ||
// }); | ||
// | ||
// expect(order.isValid()).toBeFalsy(); | ||
// }); | ||
// }); | ||
|
||
|
||
|
||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Backbone from 'backbone'; | ||
import Order from 'models/order'; | ||
|
||
const OrderList = Backbone.Collection.extend({ | ||
model: Order, | ||
}); | ||
|
||
export default OrderList; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Backbone from 'backbone'; | ||
import Trade from 'models/trade'; | ||
|
||
const TradeList = Backbone.Collection.extend({ | ||
model: Trade, | ||
}); | ||
|
||
export default TradeList; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import Backbone from 'backbone'; | ||
|
||
const Order = Backbone.Model.extend({ | ||
initialize(params) { | ||
this.buy = params.buy; | ||
this.targetPrice = params.targetPrice; | ||
this.symbol = params.symbol; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Backbone should copy all this data into the attributes automatically, which you can then access with |
||
this.quotes = params.quotes; | ||
}, | ||
|
||
validate(params) { | ||
const errors = {}; | ||
if (!params.targetPrice) { | ||
errors['price'] = 'Invalid target price!'; | ||
} | ||
|
||
// if (params.targetPrice >= matchingQuote.attributes.price) { | ||
// errors['buy'] = 'Less than current market price' | ||
// } | ||
|
||
if (Object.keys(errors).length > 0) { | ||
return errors; | ||
} else { | ||
return false; | ||
} | ||
}, | ||
}); | ||
|
||
export default Order; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import Backbone from 'backbone'; | ||
|
||
const Trade = Backbone.Model.extend({ | ||
initialize(params) { | ||
this.symbol = params.symbol; | ||
this.buy = params.buy; | ||
this.price = params.price; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, should not need to explicitly copy attributes here. |
||
}, | ||
}); | ||
|
||
export default Trade; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import Backbone from 'backbone'; | ||
import $ from 'jquery'; | ||
import Order from '../models/order'; | ||
import OrderView from './order_view'; | ||
|
||
const OrderListView = Backbone.View.extend({ | ||
initialize(params) { | ||
this.template = params.template; | ||
this.bus = params.bus; | ||
this.quotes = params.quotes; | ||
this.listenTo(this.model, 'update', this.render); | ||
}, | ||
|
||
render() { | ||
const list = this.$('#orders'); | ||
list.empty(); | ||
this.model.each((order) => { | ||
const orderView = new OrderView({ | ||
model: order, | ||
template: this.template, | ||
tagName: 'li', | ||
className: 'order', | ||
quotes: this.quotes, | ||
bus: this.bus, | ||
}); | ||
list.prepend(orderView.render().$el); | ||
}); | ||
return this; | ||
}, | ||
|
||
events: { | ||
'click .btn-buy': 'buyOrder', | ||
'click .btn-sell': 'sellOrder', | ||
}, | ||
|
||
createOrder(buy) { | ||
event.preventDefault(); | ||
$('.form-errors').empty(); // clear errors when new order is placed | ||
const symbol = this.$(`[name=symbol]`).val(); | ||
const targetPrice = parseFloat(this.$(`[name=target-price]`).val()); | ||
const orderData = { | ||
buy, // buy: buy | ||
targetPrice, // targetPrice: targetPrice | ||
symbol, // symbol: symbol | ||
}; | ||
|
||
const newOrder = new Order(orderData); | ||
|
||
if (newOrder.isValid()) { | ||
this.model.add(newOrder); // add to order list | ||
} else { | ||
newOrder.destroy(); | ||
this.errorMessage(newOrder.validationError); | ||
} | ||
}, | ||
|
||
errorMessage(errors) { | ||
Object.entries(errors).forEach((error)=> { | ||
$('.form-errors').prepend(`<h3>${error[1]}</h3>`); | ||
}) | ||
}, | ||
|
||
buyOrder: function(event) { | ||
event.preventDefault(); | ||
const order = this.createOrder(true); | ||
}, | ||
|
||
sellOrder: function(event) { | ||
event.preventDefault(); | ||
const order = this.createOrder(false); | ||
}, | ||
}); | ||
|
||
export default OrderListView; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import Backbone from 'backbone'; | ||
import Trade from '../models/trade'; | ||
|
||
const OrderView = Backbone.View.extend({ | ||
initialize(params) { | ||
this.template = params.template; | ||
this.bus = params.bus; | ||
this.quotes = params.quotes; | ||
this.listenTo(this, 'deleteOrder', this.deleteOrder); | ||
this.listenTo(params.quotes, 'change', this.placeOrder); | ||
}, | ||
|
||
render() { | ||
const compiledTemplate = this.template(this.model.toJSON()); | ||
this.$el.html(compiledTemplate); | ||
return this; | ||
}, | ||
|
||
events: { | ||
'click button.btn-cancel': 'deleteOrder', | ||
}, | ||
|
||
deleteOrder() { | ||
this.model.destroy(); | ||
this.remove(); | ||
}, | ||
|
||
placeOrder() { | ||
const trade = new Trade({ | ||
buy: this.model.buy, | ||
price: this.model.targetPrice, | ||
symbol: this.model.symbol, | ||
}); | ||
|
||
// bySymbol is custom filter created in quote_list | ||
const matchingQuote = this.quotes.bySymbol(this.model.symbol); | ||
|
||
if (this.model.buy) { | ||
if (this.model.targetPrice < matchingQuote.attributes.price) { | ||
matchingQuote.buy(); | ||
this.bus.trigger('addTrade', trade); // newTrade() in trade_list_view | ||
this.trigger('deleteOrder'); // deleteOrder() above ^^ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not call |
||
} | ||
} else if (!this.model.buy) { | ||
if (this.model.targetPrice > matchingQuote.attributes.price) { | ||
matchingQuote.sell(); | ||
this.bus.trigger('addTrade', trade); // newTrade() in trade_list_view | ||
this.trigger('deleteOrder'); // deleteOrder() above ^^ | ||
} | ||
} | ||
}, | ||
}); | ||
|
||
export default OrderView; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that you broke this out as a separate function on the collection. Good organization!