return (next) => async (action) => { switch (action.type) { case ORDER_REQUESTED: { const requestedOrder = { ...action.payload } if (typeof requestedOrder.price === 'undefined') { /* build market order */ if (typeof requestedOrder.quantity === 'undefined') { store.dispatch({ type: ORDER_FAILED, payload: new Error('missing order quantity') }) break } const { buy, sell } = await client.getMarketPrice(requestedOrder.identifier) const direction = sign(requestedOrder.quantity) if (direction === 1) { requestedOrder.price = buy } else { requestedOrder.price = sell } } requestedOrder.commission = client.calculateCommission(requestedOrder) store.dispatch({ type: ORDER_CREATED, payload: requestedOrder }) break } case ORDER_CREATED: { try { const executedOrder = await client.executeOrder({ ...action.payload }) store.dispatch({ type: ORDER_PLACED, payload: { ...executedOrder } }) } catch (error) { store.dispatch({ type: ORDER_FAILED, payload: error }) } break } case ORDER_CANCEL: { try { const id = await client.cancelOrder({ ...action.payload }) const cancelledOrder = store.getState().getIn(['orders', id]) store.dispatch({ type: ORDER_CANCELLED, payload: { ...cancelledOrder } }) } catch (error) { store.dispatch({ type: ORDER_FAILED, payload: error }) } break } default: break } return next(action) }
export default (state = initialState, action) => { switch (action.type) { case INITIALIZED: { if (action.payload.initialStates.positions) { // TODO validate supplied data const initial = action.payload.initialStates.positions for (const key of initialState.keys()) { if (typeof initial[key] !== 'undefined') { state = state.mergeIn([key], initial[key]) } } } const history = Map({ instruments: state.get('instruments'), timestamp: action.payload.timestamp }) state = state.update('history', list => list.push(history)) return state } case ORDER_FILLED: { const order = action.payload const identifier = order.identifier const direction = sign(order.quantity) /* this is a new instrument, so add it and exit early */ if (!state.hasIn(['instruments', identifier])) { /* value = quantity * price */ const value = n(multiply(b(order.quantity), b(order.price))) return state.setIn(['instruments', identifier], Map({ quantity: order.quantity, value, price: order.price })) } let instrument = state.getIn(['instruments', identifier]) /* update average aquired price if buying */ if (direction === 1) { /* price = * (order.price * order.quantity + (instrument.quantity * instrument.price)) / * (instrument.quantity + order.quantity) */ const price = n(chain(b(order.price)) .multiply(b(order.quantity)) .add(multiply(b(instrument.get('quantity')), b(instrument.get('price')))) .divide(add(b(instrument.get('quantity')), b(order.quantity))) .done()) instrument = instrument.set('price', price) } /* update quantity */ /* quantity = instrument.quantity + order.quantity */ const quantity = n(add(b(instrument.get('quantity')), b(order.quantity))) /* update value */ /* value = order.price * (instrument.quantity + order.quantity) */ const value = n(chain(b(order.price)) .multiply(add(b(instrument.get('quantity')), b(order.quantity))) .done()) instrument = instrument.merge({ quantity, value }) /* delete position and exit early if quantity is now 0 */ if (instrument.get('quantity') === 0) { return state.deleteIn(['instruments', identifier]) } state = state.setIn(['instruments', identifier], instrument) /* update history */ const history = Map({ instruments: state.get('instruments'), timestamp: order.timestamp }) state = state.update('history', list => list.push(history)) return state } case BAR_RECEIVED: { const bar = action.payload const identifier = bar.identifier if (state.hasIn(['instruments', identifier])) { /* create a zero-value position if non-existent, then do nothing more */ const quantity = state.getIn(['instruments', identifier, 'quantity']) const marketPrice = bar.close /* calculate the new the value of the position */ /* value = quantity * marketPrice */ const value = n(chain(b(quantity)).multiply(b(marketPrice)).done()) /* assign the new position */ state = state.setIn(['instruments', identifier, 'value'], value) } /* update history */ const history = Map({ instruments: state.get('instruments'), timestamp: bar.timestamp }) state = state.update('history', list => list.push(history)) return state } default: { return state } } }
var math = require('mathjs'); //導入math函數進行數學運算 //常用四則運算 console.log(math.add(2,3)); //加法(2+3) console.log(math.subtract(5,3)); //減法(5-3) console.log(math.multiply(7,3)); //乘法(7*3) console.log(math.divide(9,3)); //除法(9/3) console.log(math.mod(8,3)); //取餘數(8%3,8mod3) console.log(math.abs(-8)); //絕對值 console.log(math.sign([3,5,-2,0,2])); //判斷正負號(正->1,負->-1,零->0) console.log(math.unaryMinus([-9,7])); //反轉正負號 console.log(math.ceil([3.2,3.8,-4.7])); //最大整數 console.log(math.floor([3.2,3.8,-4.7])); //最小整數 console.log(math.fix([3.2,3.8,-4.7])); //無條件捨去 console.log(math.round(math.pi,3)); //四捨五入且取到小數點後第3位 console.log(math.square(2)); //二次方(2^2) console.log(math.cube(2)); //三次方(2^3) console.log(math.pow(2,4)); //乘冪(2^4) console.log(math.sqrt(121)); //開根號 console.log(math.nthRoot(27,3)); //指定開幾次根號 console.log(math.exp(2)); //指數 console.log(math.log(1024,2)); //對數 console.log(math.log10(1000)); //固定10為底對數 console.log(math.gcd(25,15,-10)); //最大公因數 console.log(math.lcm(6,21,5)); //最小公倍數 console.log(math.unit('5 cm').value); //以公尺為單位顯示大小 console.log(math.unit('5 m').value); //以公尺為單位顯示大小 console.log(math.dotMultiply([3,2],[5,7])); //矩陣乘法 console.log(math.dotDivide([9,8],[3,2])); //矩陣除法 console.log(math.dotPow([[1,2],[3,4]],2)); //矩陣乘冪 console.log('---------------------------------------');