Added NATS server and frontend code to connect to it
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import {pub, sub} from './pubsub.js';
|
||||
import state from './state.js';
|
||||
import redraw from './redraw.js';
|
||||
|
||||
// "raw" event listeners, which publish meaningful events, which are listened-to further-down:
|
||||
// ...
|
||||
|
||||
|
||||
// "meaningful" event listeners:
|
||||
//sub('set-current-node', (node_vm)=>{
|
||||
// state.current_node_vm = node_vm;
|
||||
// redraw();
|
||||
// });
|
||||
|
||||
// connect to NATS thru WebSockets:
|
||||
import { connect, StringCodec } from "nats.ws";
|
||||
const strcodec = StringCodec();
|
||||
const init_nats = async function(){
|
||||
const nc = await connect({servers: "ws://localhost:4223"});
|
||||
console.log(nc);
|
||||
|
||||
(async ()=>{
|
||||
const sub = nc.subscribe('price');
|
||||
for await (const msg of sub){
|
||||
console.log(`[${sub.getProcessed()}]: ${strcodec.decode(msg.data)}`);
|
||||
}
|
||||
})();
|
||||
(async ()=>{
|
||||
const sub = nc.subscribe('close');
|
||||
for await (const msg of sub){
|
||||
nc.close();
|
||||
console.log('closed!');
|
||||
break;
|
||||
}
|
||||
})();
|
||||
|
||||
nc.publish('price', strcodec.encode('4.23'));
|
||||
nc.publish('price', strcodec.encode('5.00'));
|
||||
//nc.close();
|
||||
};
|
||||
init_nats()
|
||||
|
||||
|
||||
export default null;
|
||||
@@ -0,0 +1,15 @@
|
||||
import {elementOpen as o, elementClose as c, text as t} from 'incremental-dom';
|
||||
import state from '../state.js';
|
||||
import {pub} from '../pubsub.js';
|
||||
|
||||
|
||||
const App = ()=>{
|
||||
o('div', null, null,
|
||||
'id', 'header');
|
||||
o('h1');
|
||||
t('Options Calendar-Spread Optimizer');
|
||||
c('h1');
|
||||
c('div');
|
||||
}
|
||||
|
||||
export default App;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,33 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.node, .node > .content, .node > .node-children-container {
|
||||
display: inline-block;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.node {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.node > .content {
|
||||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
||||
}
|
||||
.node[currently-selected-node] > .content {
|
||||
/* background-color: #7ea6fc; */
|
||||
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
|
||||
}
|
||||
|
||||
.node > .content > textarea {
|
||||
background: transparent;
|
||||
resize: none;
|
||||
width: 80em;
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.node > .node-children-container {
|
||||
margin-left: 5em;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Calendar Optimizer</title>
|
||||
<link rel="stylesheet" href="index.css"></link>
|
||||
</head>
|
||||
<body>
|
||||
<script type='module' src="index.js"></script>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,17 @@
|
||||
import redraw from './redraw.js';
|
||||
import state from './state.js';
|
||||
import x from './behaviors.js';
|
||||
|
||||
|
||||
// bootstrap initial state:
|
||||
|
||||
|
||||
redraw();
|
||||
|
||||
|
||||
/* TODO */
|
||||
/*
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Collect contiguous ranges. These are where the underlying is expected to be at the front-month.
|
||||
For each strike in the contiguous ranges, collect all front-month/back-month combinations
|
||||
For each of these front-month/back-month combinations, calculate PNL (by %-return) assuming the underlying is at each strike in the contiguous ranges
|
||||
For each of these potential underlying close-prices, choose the best front-month/back-month combo.
|
||||
For each ...
|
||||
*/
|
||||
|
||||
export const calculateBestCombinationOfCalendars(){
|
||||
let cheapest = null;
|
||||
front_months.forEach(front_month=>{
|
||||
front_month.ranges.forEach(range=>{
|
||||
range.back_months.forEach(back_month=>{
|
||||
// begin by making a calendar at every available strike in the range.
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// global PubSub instance:
|
||||
import PubSub from 'PubSubJS';
|
||||
|
||||
const pubsub = PubSub();
|
||||
export const {pub, sub, unsub} = pubsub;
|
||||
|
||||
export default pubsub;
|
||||
@@ -0,0 +1,10 @@
|
||||
import {patch} from 'incremental-dom';
|
||||
import App from './components/App.js';
|
||||
|
||||
export const redraw = ()=>{
|
||||
const root = document.getElementById('root');
|
||||
|
||||
patch(root, App);
|
||||
}
|
||||
|
||||
export default redraw;
|
||||
@@ -0,0 +1,22 @@
|
||||
const someFn = null;
|
||||
const state = {
|
||||
front_months: { // front months, i.e. calendar expiry, at which the user has an opinion on where the underlying price may be
|
||||
"2022-03-11": {
|
||||
underlying_ranges: [ // underlying-price ranges, at which the user thinks the underlying price may be, at expiry (i.e. front-month)
|
||||
{
|
||||
from: 300,
|
||||
to: 400,
|
||||
back_months: { // back months, for which the user has an opinion on what the IV-smile will look like, given that the underying price is within range
|
||||
"2022-04-17": {
|
||||
iv_fn: someFn // signature: (underlying_price, strike_price, dte); the function internally stores the shape of the IV-smile as a function of percentage-diff-between-underlying-and-strike, so that the function can be run for any underlying value in the range, and of course any strike.
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default state;
|
||||
Reference in New Issue
Block a user