Merge pull request #42 from mikebryant/integrating-probability

feat: Integrating probability
master
Mike Bryant 5 years ago committed by GitHub
commit ea190f6d38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -37,6 +37,33 @@
</span> </span>
</div> </div>
</div> </div>
<div class="row">
<div class="col s12">
<h5>Probability</h5>
<div class="row">
<div class="col s4">
<div class="input-field">
<select id="previous_pattern">
<option value="-1" selected>(unknown)</option>
<!-- Choices are ordered by increasing desirability, not code ID order -->
<option value="2">Decreasing</option>
<option value="0">Fluctuating</option>
<option value="3">Small spike</option>
<option value="1">Large spike</option>
</select>
<label for="previous_pattern">Last weeks pattern</label>
</div>
</div>
<div class="col s6">
<div class="input-field">
<span>
<b>Last weeks pattern</b> affects the probability of patterns for this week. If you know it, select it to see probabilities for this week. <em>(optional)</em>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<h5>Daisy Mae</h5> <h5>Daisy Mae</h5>
@ -152,6 +179,7 @@
<thead> <thead>
<tr> <tr>
<th rowspan="2">Pattern</th> <th rowspan="2">Pattern</th>
<th rowspan="2">% Chance</th>
<th rowspan="2">Sunday</th> <th rowspan="2">Sunday</th>
<th colspan="2">Monday</th> <th colspan="2">Monday</th>
<th colspan="2">Tuesday</th> <th colspan="2">Tuesday</th>

@ -1,3 +1,44 @@
const PATTERN = {
FLUCTUATING: 0,
LARGE_SPIKE: 1,
DECREASING: 2,
SMALL_SPIKE: 3,
};
const PATTERN_COUNTS = {
[PATTERN.FLUCTUATING]: 56,
[PATTERN.LARGE_SPIKE]: 7,
[PATTERN.DECREASING]: 1,
[PATTERN.SMALL_SPIKE]: 8,
}
const PROBABILITY_MATRIX = {
[PATTERN.FLUCTUATING]: {
[PATTERN.FLUCTUATING]: 0.20,
[PATTERN.LARGE_SPIKE]: 0.30,
[PATTERN.DECREASING]: 0.15,
[PATTERN.SMALL_SPIKE]: 0.35,
},
[PATTERN.LARGE_SPIKE]: {
[PATTERN.FLUCTUATING]: 0.50,
[PATTERN.LARGE_SPIKE]: 0.05,
[PATTERN.DECREASING]: 0.20,
[PATTERN.SMALL_SPIKE]: 0.25,
},
[PATTERN.DECREASING]: {
[PATTERN.FLUCTUATING]: 0.25,
[PATTERN.LARGE_SPIKE]: 0.45,
[PATTERN.DECREASING]: 0.05,
[PATTERN.SMALL_SPIKE]: 0.25,
},
[PATTERN.SMALL_SPIKE]: {
[PATTERN.FLUCTUATING]: 0.45,
[PATTERN.LARGE_SPIKE]: 0.25,
[PATTERN.DECREASING]: 0.15,
[PATTERN.SMALL_SPIKE]: 0.15,
},
};
function minimum_rate_from_given_and_base(given_price, buy_price) { function minimum_rate_from_given_and_base(given_price, buy_price) {
return 10000 * (given_price - 1) / buy_price; return 10000 * (given_price - 1) / buy_price;
} }
@ -177,7 +218,7 @@ function* generate_pattern_0_with_lengths(given_prices, high_phase_1_len, dec_ph
}); });
} }
yield { yield {
pattern_description: "high, decreasing, high, decreasing, high", pattern_description: "Fluctuating",
pattern_number: 0, pattern_number: 0,
prices: predicted_prices prices: predicted_prices
}; };
@ -285,7 +326,7 @@ function* generate_pattern_1_with_peak(given_prices, peak_start) {
}); });
} }
yield { yield {
pattern_description: "decreasing middle, high spike, random low", pattern_description: "Large spike",
pattern_number: 1, pattern_number: 1,
prices: predicted_prices prices: predicted_prices
}; };
@ -351,7 +392,7 @@ function* generate_pattern_2(given_prices) {
max_rate -= 300; max_rate -= 300;
} }
yield { yield {
pattern_description: "consistently decreasing", pattern_description: "Decreasing",
pattern_number: 2, pattern_number: 2,
prices: predicted_prices prices: predicted_prices
}; };
@ -531,7 +572,7 @@ function* generate_pattern_3_with_peak(given_prices, peak_start) {
} }
yield { yield {
pattern_description: "decreasing, spike, decreasing", pattern_description: "Small spike",
pattern_number: 3, pattern_number: 3,
prices: predicted_prices prices: predicted_prices
}; };
@ -564,8 +605,30 @@ function* generate_possibilities(sell_prices, first_buy) {
} }
} }
function analyze_possibilities(sell_prices, first_buy) { function row_probability(possibility, previous_pattern) {
return PROBABILITY_MATRIX[previous_pattern][possibility.pattern_number] / PATTERN_COUNTS[possibility.pattern_number];
}
function get_probabilities(possibilities, previous_pattern) {
if (typeof previous_pattern === 'undefined' || Number.isNaN(previous_pattern) || previous_pattern === null || previous_pattern < 0 || previous_pattern > 3) {
return possibilities
}
var max_percent = possibilities.map(function (poss) {
return row_probability(poss, previous_pattern);
}).reduce(function (prev, current) {
return prev + current;
}, 0);
return possibilities.map(function (poss) {
poss.probability = row_probability(poss, previous_pattern) / max_percent;
return poss;
});
}
function analyze_possibilities(sell_prices, first_buy, previous_pattern) {
generated_possibilities = Array.from(generate_possibilities(sell_prices, first_buy)); generated_possibilities = Array.from(generate_possibilities(sell_prices, first_buy));
generated_possibilities = get_probabilities(generated_possibilities, previous_pattern);
global_min_max = []; global_min_max = [];
for (var day = 0; day < 14; day++) { for (var day = 0; day < 14; day++) {
@ -585,7 +648,7 @@ function analyze_possibilities(sell_prices, first_buy) {
} }
generated_possibilities.push({ generated_possibilities.push({
pattern_description: "predicted min/max across all patterns", pattern_description: "All patterns",
pattern_number: 4, pattern_number: 4,
prices: global_min_max, prices: global_min_max,
}); });

@ -10,10 +10,12 @@ const getSellFields = function () {
const sell_inputs = getSellFields() const sell_inputs = getSellFields()
const buy_input = $("#buy") const buy_input = $("#buy")
const first_buy_field = $("#first_buy"); const first_buy_field = $("#first_buy");
const previous_pattern_input = $("#previous_pattern");
//Functions //Functions
const fillFields = function (prices, first_buy) { const fillFields = function (prices, first_buy, previous_pattern) {
first_buy_field.prop("checked", first_buy); first_buy_field.prop("checked", first_buy);
previous_pattern_input.val(previous_pattern);
buy_input.focus(); buy_input.focus();
buy_input.val(prices[0] || '') buy_input.val(prices[0] || '')
@ -36,10 +38,11 @@ const initialize = function () {
try { try {
const prices = getPrices() const prices = getPrices()
const first_buy = getFirstBuyState(); const first_buy = getFirstBuyState();
const previous_pattern = getPreviousPatternState();
if (prices === null) { if (prices === null) {
fillFields([], first_buy) fillFields([], first_buy, previous_pattern)
} else { } else {
fillFields(prices, first_buy) fillFields(prices, first_buy, previous_pattern)
} }
$(document).trigger("input"); $(document).trigger("input");
} catch (e) { } catch (e) {
@ -48,15 +51,19 @@ const initialize = function () {
$("#reset").on("click", function () { $("#reset").on("click", function () {
first_buy_field.prop('checked', false); first_buy_field.prop('checked', false);
$("select").val(null);
$("input").val(null).trigger("input"); $("input").val(null).trigger("input");
}) })
$('select').formSelect();
} }
const updateLocalStorage = function (prices, first_buy) { const updateLocalStorage = function (prices, first_buy, previous_pattern) {
try { try {
if (prices.length !== 14) throw "The data array needs exactly 14 elements to be valid" if (prices.length !== 14) throw "The data array needs exactly 14 elements to be valid"
localStorage.setItem("sell_prices", JSON.stringify(prices)) localStorage.setItem("sell_prices", JSON.stringify(prices))
localStorage.setItem("first_buy", JSON.stringify(first_buy)); localStorage.setItem("first_buy", JSON.stringify(first_buy));
localStorage.setItem("previous_pattern", JSON.stringify(previous_pattern));
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} }
@ -71,6 +78,10 @@ const getFirstBuyState = function () {
return JSON.parse(localStorage.getItem('first_buy')) return JSON.parse(localStorage.getItem('first_buy'))
} }
const getPreviousPatternState = function () {
return JSON.parse(localStorage.getItem('previous_pattern'))
}
const getPricesFromLocalstorage = function () { const getPricesFromLocalstorage = function () {
try { try {
const sell_prices = JSON.parse(localStorage.getItem("sell_prices")); const sell_prices = JSON.parse(localStorage.getItem("sell_prices"));
@ -112,14 +123,15 @@ const getSellPrices = function () {
}) })
} }
const calculateOutput = function (data, first_buy) { const calculateOutput = function (data, first_buy, previous_pattern) {
if (isEmpty(data)) { if (isEmpty(data)) {
$("#output").html(""); $("#output").html("");
return; return;
} }
let output_possibilities = ""; let output_possibilities = "";
for (let poss of analyze_possibilities(data, first_buy)) { for (let poss of analyze_possibilities(data, first_buy, previous_pattern)) {
var out_line = "<tr><td>" + poss.pattern_description + "</td>" var out_line = "<tr><td>" + poss.pattern_description + "</td>"
out_line += `<td>${Number.isFinite(poss.probability) ? ((poss.probability * 100).toPrecision(3) + '%') : '—'}</td>`;
for (let day of poss.prices.slice(1)) { for (let day of poss.prices.slice(1)) {
if (day.min !== day.max) { if (day.min !== day.max) {
out_line += `<td>${day.min}..${day.max}</td>`; out_line += `<td>${day.min}..${day.max}</td>`;
@ -138,15 +150,17 @@ const update = function () {
const sell_prices = getSellPrices(); const sell_prices = getSellPrices();
const buy_price = parseInt(buy_input.val()); const buy_price = parseInt(buy_input.val());
const first_buy = first_buy_field.is(":checked"); const first_buy = first_buy_field.is(":checked");
const previous_pattern = parseInt(previous_pattern_input.val());
buy_input.prop('disabled', first_buy); buy_input.prop('disabled', first_buy);
const prices = [buy_price, buy_price, ...sell_prices]; const prices = [buy_price, buy_price, ...sell_prices];
if (!window.price_from_query) { if (!window.price_from_query) {
updateLocalStorage(prices, first_buy); updateLocalStorage(prices, first_buy, previous_pattern);
} }
calculateOutput(prices, first_buy); calculateOutput(prices, first_buy, previous_pattern);
} }
$(document).ready(initialize); $(document).ready(initialize);
$(document).on("input", update); $(document).on("input", update);
$(previous_pattern_input).on("change", update);

Loading…
Cancel
Save