Блог им. NektoFinkelmaer
<!DOCTYPE html> <meta charset="utf-8"> <html> <body> <a href="SomeLink" id="ButtonLoadData" download><input type='button' class='button-css' value='Load data...' /></a> <input type="file" onChange="readFiles(this);" multiple /> <br> <br> <table id="table" border="1"></table> <script> // загрузка файла var DimTikers = []; var DimColumns = []; var iMoex; /* var Cost = { var Period; var Open; var Close; var Min; var Max; var Percent; }; var DimTiker={ var Tiker; var Dividends[]; var Cost = []; }; */ function readFiles(e) { const files = e.files; readOneFile(0,files); function readOneFile(indexFiles,files){ if (indexFiles>=files.length) { return; } const file = files[indexFiles]; const reader = new FileReader(); reader.addEventListener('loadend', event => { let content = event.target.result; let rows = content.split(/\r\n|\r|\n/g); for (j=0; j<rows.length; ++j) { let row = rows[j].split(";"); if (row[0]!="<TICKER>" && rows[j] ) { PosTiker=DimTikers.findIndex(item => item.Tiker == row[0]); if (PosTiker==-1) {PosTiker=DimTikers.length; DimTikers[PosTiker]={};DimTikers[PosTiker].Cost=[];} DimTikers[PosTiker].Tiker=row[0]; if (DimColumns.findIndex(item => item==row[2])==-1) DimColumns[DimColumns.length]=row[2]; DimTikers[PosTiker].Cost[row[2]]={Period:row[2], Open:row[4], Close:row[7], Low:row[6], High:row[5], Percent:( row[4]==0 ? 0 : Math.trunc(10000* (row[7]-row[4])/row[4] )/100) }; } } if (indexFiles+1==files.length){ DimColumns.sort(function(a,b){ //console.log("-"+a+" "+b); if (a>b) return -1; else if (a<b) return 1; else return 0; } ); for (let i = 0; i < DimTikers.length; i++) { for (let j=0; j<DimColumns.length; j++){ try { DimTikers[i].Cost[DimColumns[j]].Percent = (DimTikers[i].Cost[DimColumns[j+1]].Close==0) ? 0 : Math.trunc(10000*(DimTikers[i].Cost[DimColumns[j]].Close-DimTikers[i].Cost[DimColumns[j+1]].Close) /DimTikers[i].Cost[DimColumns[j+1]].Close)/100; } catch{ try { DimTikers[i].Cost[DimColumns[j]].Percent = (DimTikers[i].Cost[DimColumns[j]].Open==0) ? 0 : Math.trunc(10000*(DimTikers[i].Cost[DimColumns[j]].Close-DimTikers[i].Cost[DimColumns[j]].Open) /DimTikers[i].Cost[DimColumns[j]].Open)/100; } catch{ } } } } DimTikers.sort(function(a,b){ if (a.Cost[DimColumns[1]].Percent<b.Cost[DimColumns[1]].Percent) return 1; else if (a.Cost[DimColumns[1]].Percent>b.Cost[DimColumns[1]].Percent) return -1; else return 0;}); //console.log(DimTikers); let table = document.querySelector('#table'); let tr = document.createElement('tr'); let td = document.createElement('td'); tr.appendChild(td); let td3 = document.createElement('td'); //Last td3.innerHTML='Last'; tr.appendChild(td3); let td1 = document.createElement('td'); //Buy td1.innerHTML='Buy'; tr.appendChild(td1); let td2 = document.createElement('td'); //Sell td2.innerHTML='Sell'; tr.appendChild(td2); for (let i=0; i<DimColumns.length; i++){ let td = document.createElement('td'); td.innerHTML=DimColumns[i].substring(6,8)+"."+DimColumns[i].substring(4,6); tr.appendChild(td); } table.appendChild(tr); iMoex=DimTikers.find(item => item.Tiker == "Индекс МосБиржи"); for (let i = 0; i < DimTikers.length; i++) { let tr = document.createElement('tr'); //align="left" let td = document.createElement('td'); td.style.align="right"; td.innerHTML=DimTikers[i].Tiker; tr.appendChild(td); let td3 = document.createElement('td'); td3.style.align="left"; //last td3.innerHTML=(DimTikers[i].Cost[DimColumns[0]].Close).toString().replace(".",","); tr.appendChild(td3); let td1 = document.createElement('td'); td1.style.align="left"; //buy //td1.innerHTML=(Math.trunc(100*(DimTikers[i].Cost[DimColumns[1]].High-(DimTikers[i].Cost[DimColumns[1]].High-DimTikers[i].Cost[DimColumns[2]].Low)/3))/100).toString().replace(".",","); td1.innerHTML=(Math.trunc(100*(DimTikers[i].Cost[DimColumns[1]].Open*1.005))/100).toString().replace(".",","); console.log(""+DimTikers[i].Tiker+" "+DimTikers[i].Cost[DimColumns[1]].High+" "+DimTikers[i].Cost[DimColumns[2]].Low+" "+(DimTikers[i].Cost[DimColumns[1]].High-DimTikers[i].Cost[DimColumns[2]].Low)/3); tr.appendChild(td1); let td2 = document.createElement('td'); td2.style.align="left"; //Sell //td2.innerHTML=(Math.trunc(100*(DimTikers[i].Cost[DimColumns[1]].High-(DimTikers[i].Cost[DimColumns[1]].High-DimTikers[i].Cost[DimColumns[2]].Low)/1.5))/100).toString().replace(".",","); td2.innerHTML=(Math.trunc(100*(DimTikers[i].Cost[DimColumns[1]].Open*0.995))/100).toString().replace(".",","); tr.appendChild(td2); let summa=0; for (let j=0; j<DimColumns.length; j++){ let td = document.createElement('td'); let color="black"; try{ if (iMoex.Tiker==DimTikers[i].Tiker) color="black"; else color = (iMoex.Cost[DimColumns[j]].Percent < DimTikers[i].Cost[DimColumns[j]].Percent) ? "green":"red"; } catch { color="yellow"; } try { td.innerHTML = '<span style="color: '+color+';">'+DimTikers[i].Cost[DimColumns[j]].Percent.toString().replace(".",",")+'</span>'; } catch { } tr.appendChild(td); } table.appendChild(tr); } } }); reader.readAsText(file); readOneFile(indexFiles+1,files); } } </script> <script> var myUrl0='https://mfd.ru/export/handler.ashx/IMOEX_1week.txt?TickerGroup=14&Tickers=140335&Alias=false&Alias149952=IMOEX&Period=7&timeframeValue=1&timeframeDatePart=day&'; var myUrl='https://mfd.ru/export/handler.ashx/mfdexport.txt?TickerGroup=16&Tickers=145325%2C248695%2C246238%2C59186%2C237123%2C251365%2C231825%2C56252%2C202443%2C66525%2C66538%2C41369%2C183%2C258%2C330%2C336%2C121191%2C140335%2C489%2C629%2C632%2C832%2C82984%2C716%2C51353%2C826%2C913%2C948%2C330%2C336%2C121191%2C140335%2C489%2C629%2C632%2C832%2C82984%2C716%2C51353%2C826%2C913%2C948%2C1019%2C1279%2C103315%2C1373%2C54102%2C1383%2C246271%2C1389%2C1463%2C1464%2C913%2C948%2C1019%2C1279%2C103315%2C1373%2C54102%2C1383%2C246271%2C1389%2C1463%2C1476%2C1503%2C1542%2C1543%2C1613%2C1614%2C1658%2C37859%2C1712%2C107301&Alias=false&Period=7&timeframeValue=1&timeframeDatePart=day&'; var myUrl1='&SaveFormat=0&SaveMode=0&FileName=mfdexport.txt&FieldSeparator=%253b&DecimalSeparator=.&DateFormat=yyyyMMdd&TimeFormat=HHmmss&DateFormatCustom=&TimeFormatCustom=&AddHeader=true&RecordFormat=0&Fill=false'; var now = new Date(); var enddata = strRight(2,"0"+now.getDate().toString())+"."+strRight(2,"0"+(now.getMonth()+1).toString())+"."+now.getFullYear().toString(); var Month=now.getMonth()-1;var year=now.getFullYear(); if (Month<0) {Month=12+Month+1; year--;}; var startdata = strRight(2,"0"+now.getDate().toString())+"."+strRight(2,"0"+Month.toString())+"."+(year).toString(); myUrl2=myUrl+"StartDate="+startdata+"&EndDate="+enddata+myUrl1; document.getElementById('ButtonLoadData').href = myUrl2; function strRight(n,str){ return str.substring(str.length-n,str.length); // параметр e - объект файла из элемента выбора /** * * @param data данные из файла CSV * @param delimiter разделитель, используемый в файле * @param firstRow пропускать или оставлять первую строку - заголовок */ function convertCSV2Array(data, delimiter = ',', firstRow = false) { return data .slice(firstRow ? data.indexOf('\n') + 1 : 0) .split('\n') .map(row => row.split(delimiter)); } } </script> </body> </html>
Итого получаем:
плюсовое направление: 80% вероятности движения 0.1%.
минусовое направление: 20% вероятности движения 0.5%
мат. ожидание:
плюсовое: 0.1 * 0.8 = 0.08%
минусовое: 0.5 * 0.2 = 0.1%
Где я ошибся?
Все верно, отрицательное.
Изменив параметры получим положительное 7 дней по 0.2 плюс, 2 дня по 0.5 минус
В основе системы постулат: Направленное движение всегда продолжается.
Для анализа выбран реальный инструмент имеющий котировки на Московской бирже
Источник котировок mfd.ru/export
Подробное описание в предыдущей публикации по ссылке в начале поста
«скорее продолжится, чем развернется».
Я добавил бы: «если движение не в затухающей фазе
и если оно не уперлось в уровень».
По мелочи есть к чему придраться, но «вцелом» со всем согласен, есть только предложение по улучшению. Но сначала дождусь «дальше интересней» — подозреваю, что вы про это улучшение сами знаете.
Очень уж у нас мысли (логика) сходятся.
В принципе, есть несколько путей, можно сказать, равноправных.
Возможностей для развития я бы сказал много.
В случае, если вы рады в ответ, так я опять же рад, что вы рады, что я рад.
И как вот из этого: можно сделать вывод: Надо бы определить сначала и в цифрах изобразить, что значит направленное. Тогда и проверить что-то возможно станет.
У каждой свечи есть тень до открытия, у 80 процентов свечей эта тень меньше полпроцента движения цены, таким образом мы может предположить, что и последующих свечей тень не превысит полпроцента. В таком случае если цена прошла этот порог, то врятли развернется, поскольку первое предположение будет не верно
Простите, если опять не понятно, как смог… Мой талант преподавателя иссяк много лет назад. 🙂
1) Если минимум текущей свечи отклонился от её открытия более чем на 0,5%, то ничто не мешает в этой же свече переписать максимум так же более чем на 0,5% от открытия. Как-то это в статистике учитывается?
2) Не ясно в какой момент входить и в какую сторону. Преодоление минимального отклонения в 0,5% никак статистически не влияет на последующее поведение цены в оставшееся время свечи. Оно по-прежнему равновероятно в обе стороны. Легко проверяется тестами.
1.Все верно, ничего не мешает, но случится это только для 20 свечей из ста (согласно статистике)
2.Опять все верно, но стоит учесть, что движение цены, в этом направлении, 70 свечей из 100 достигнет 0.7%. Не ясно только когда, и какие движение будут этому предшествовать.
Какие выводы по представленному подходу?
Вы должны выбрать период свечей, в котором статистика наиболее проявлена в нужном ключе. Для одного инструмента он более-менее стабилен.
Это всё слегка взлетит только для некоторых инструментов.
В общем случае устойчивого заработка нет. Мелкие выигрыши по 0,1-0,2% съест комиссия более чем наполовину. А добьют накопленный небольшой плюс те 20% случаев больших сливов, когда будут случаться походы к противоположным полюсам свечи.
Выводы интересны тем, что при уменьшении вероятности получения прибыли она растет.
Наилучшие показатели были 0.54% вход, 5% тейк.
Феномен не изучен, поэтому удивляет. 🙂
Следующим шагом надо увидеть, что есть инструменты и ТФ, при которых входить надо вообще в другую сторону.
А общее замечание — в вашем подходе нужно использовать логарифмы цен. Сейчас у Вас % вверх ничем не ограничен, а вниз только 100%. Статистика перекошена.
Использование сложных математических расчетов никак не влияет на движение цены. Движения случайны по определению, но есть какая то вероятность, что цена придет в нужную мне точку, весь расчет только на это.
Вероятности, на которые Вы уповаете, надо уметь считать. Или получить иным достоверным способом.
Сгенерируйте СБ. Это тоже нетривиальная задача — сгенерировать свечи, полученные по СБ. Постройте ваши линии на них. Характеристика линии входа при СБ — нулевое матожидание результата для каждой точки входа при нулевой комиссии.
Затем откладываете двойную комиссию от неё вверх и вниз для данной цены. Получите коридор, в котором выходы будут убыточными из-за комиссии.
После чего можете строить линию выходов реального инструмента. Для входа в продолжение она должна быть выше коридора входов, для входа на возврат — ниже коридора. Расстояния от выходов до коридора и есть средний доход на одну сделку (вх+вых).