Блог им. NektoFinkelmaer

ТС "Игра теней". Завязка.

ТС «Игра теней». Завязка.

Описание системы здесь​ smart-lab.ru/mobile/topic/872068/

Простыми словами:
При движении цены в одном направлении на пол-процента вероятность движения еще на одну десятую составляет 80%
При этом вероятность возврата цены к открытию составляет 20%

В публикации при расчете доходности системы была допущена ошибка, да простят меня Гаусс, Лейбниц и Стендаль, зато похвалит Росстат.
На скажу что она случайна, однако хорошо, что никто не заметил, застыдили б...

Сегодня я расскажу как увеличить доходность системы простой математикой.

Напоминаю расчет складывается из вероятности движения цены в одном направлении 80% и дополнительном движении цены еще на 0,1% также 80%.
В формуле складывается вероятность обоих событий, однако включать в формулу вероятность свершившегося события, мягко говоря не логично.

Открытие позиции происходит только при движении цены на 0,5%. Таким образом с вероятностью 80% движение цены принесет нам одну десятую процента, а не 64 как было указано.

Годовая доходность системы при данных показателях составляет 120% (200 дней 0,8% плюс, 50% дней 0,8% минус при использовании плеча срочного рынка, симметричный тейк/стоп).

На этом хорошие новости закончились.

При использовании симметричного тейк/стопа добавляются равновероятные события.
Так может сработать тейк, стоп или одно из трех.
Таким образом из 80% вероятности достижения тейка остается всего 27%.
В случае установки стопа по цене открытия дня ситуация не лучше, из 10 дней — 2 по 0,5 литра убытка против 8 дней по 100 грамм прибыли.

Что ниже точки равновесия — система генерирует убытки.

Тут и сказочке конец, кто не слушал молодец.

Простыми словами: использование стопов не уменьшает ваши убытки — напротив увеличивает их.
В принципе это все, что нужно знать о стопах, алготрейдинге и вообще о бирже.

Что же делать? Спросите вы меня… Выход есть — изменить параметры системы.

Вернемся к графикам


ТС "Игра теней". Завязка.

Увеличение потенциального дохода до 0,2 процентов при снижении вероятности его достижения до 70%
дает нам 50% годовых, теже 2 дня по 0,5 против 7 дней по 0.2, ежедневная прибыль 4 сотых процента движения базового инструмента.
Система протестирована и неплохо работает на высоколиквидных маловолатильных инструментах. Как по настоящему прикрыть ваши задницы, в смысле депозиты расскажу в следующий раз, а пока держите скрипт расчета цен открытия позиции.

скопируйте его в файл, смените расширение на html, откройте в любом браузере.

Кнопка Laod data прочитает котировки с mdf, из-за ограничений безопасности javascript скачанный файл надо открыть, для этого вторая кнопка.
Читаются котировки инструментов входящих в индекс ММВБ на дату написания скрипта, где​ то 2 года назад, хотите что то добавить — добавьте коды инструментов в строку запроса.
Если получите ошибку 500 прочитайте данные еще раз, это внутренняя ошибка сервера.

На экране появится табличка в светофорном стиле, зеленый цвет — актив лучше рынка, даже если цена снижалась, красный — хуже, даже если цена росла.
Можете сменить период свечи на недельный — поставьте период = 8, заодно проверите систему AlexChi лучшие бумаги недели, или часовой период = 6,​
не забудьте поменять период запроса данных — расчетная переменная StartDate

Сортировка таблицы по доходности предпоследней свечи — хотите по последней найдите в тексте sort, поменяйте индекс массива на 0.
last — последняя цена, Buy — открытие + 0,5%, Sell — открытие — 0,5 %

Дальше интересней — не переключайтесь....

<!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>


★3
34 комментария
Если кто то знает как вставить сюда скрипт расскажите, будьте ласковы…
avatar
При движении цены в одном направлении на пол-процента вероятность движения еще на одну десятую составляет 80%
При этом вероятность возврата цены к открытию составляет 20%

Итого получаем:

плюсовое направление: 80% вероятности движения 0.1%.
минусовое направление: 20% вероятности движения 0.5%

мат. ожидание:

плюсовое: 0.1 * 0.8 = 0.08%
минусовое: 0.5 * 0.2 = 0.1%

Где я ошибся?
avatar
Replikant_mih, 8 дней по 0.1 плюс, 2 дня по 0.5 минус

Все верно, отрицательное.

Изменив параметры получим положительное 7 дней по 0.2 плюс, 2 дня по 0.5 минус
avatar
Nekto Finkelmaer, а, это было начало рассуждения, я думал это основа стратегии и дальше не стал особо читать).
avatar
Максим Ерофеев,

В основе системы постулат: Направленное движение всегда продолжается.
Для анализа выбран реальный инструмент имеющий котировки на Московской бирже
Источник котировок mfd.ru/export

Подробное описание в предыдущей публикации по ссылке в начале поста
avatar
Nekto Finkelmaer, постулат звучит чуть по-другому:
«скорее продолжится, чем развернется».
Я добавил бы: «если движение не в затухающей фазе
и если оно не уперлось в уровень».

По мелочи есть к чему придраться, но «вцелом» со всем согласен, есть только предложение по улучшению. Но сначала дождусь «дальше интересней» — подозреваю, что вы про это улучшение сами знаете.
Очень уж у нас мысли (логика) сходятся.
avatar
VladMih, скоро узнаем, знаю или нет, даже самому интересно🙂
avatar
Nekto Finkelmaer, мне еще интересней! 
В принципе, есть несколько путей, можно сказать, равноправных.
Возможностей для развития я бы сказал много.
avatar
Активируйте, пожалуйста, windows
Неолиберальный тоталитаризм, Майкрософт настолько милостив, даже более милостив, чем мой Бог, который позволяет мне быть атеистом, и не возражает против использования исключительных интеллектуальных прав безвозмездно.
avatar
Сломается.
avatar
GAURANGA, вам виднее.
avatar
Tуземец, рад, что доставил вам удовольствие.

В случае, если вы рады в ответ, так я опять же рад, что вы рады, что я рад.
avatar
Блин. Вы все такие умные математики, что жуть просто берёт и колени трястись начинают при виде тех цифер, что выше двух и имеют больше знаков нежели просто плюс и минус. Ну, а если серьёзно, то прежде чем писать код для робота, нужно разобраться досконально с самим исходным (кодом) рынка. Какие в жопу вероятности и проценты у вас берутся? Это возможно и работает на боле менее спокойном рынке… Хотя слово Возможно это скорее для поиграть. В любом месте всегда присутствует первое, изначальное место то откуда цена поворачивает, на откат либо для продолжения движения. Это то место где стоп всегда минимален. а зачастую ещё и прибылен. Такая точка входа всегда одна и неизменная в своём повторении. На любом рынке за исключением Форекс, хотя и там всё работает но с уточнением. Разберите для начала код рынка, а после делайте роботов. И код для робота в этом случае будет минимальным, а кол-во прибыльных сделок максимальным. К этому нужно стремиться, а не перебирать теории вероятностей.
avatar
Андрей &, простите, неловко вышло, но в жопу у меня ничего не берется.
avatar
Nekto Finkelmaer, Дело не в жопе, а не в продуманности стратегии. Возможно я не совсем понял сути, но перечитал несколько раз. Смысл конечно есть, но цена внезапного стопа весьма велика. Быть может, стоит несколько пересмотреть стратегию? Взять за исходную часовой ТФ. Робот автоматически ищет наивысшую точку обновившегося пика цены и при движении рынка в обратную сторону, бот, отсчитывает от образовавшегося максимума те самые 0,5% и открывает сделку в направлении движения? В таком варианте есть более высокая вероятность взятия более значимого профита нежели сотые доли. Единственное, чему робота нужно научить это грамотному закрытию сделок, что бы вытащить из позиции максимально возможную прибыль. Мой робот так и работает. Подхватывает мною открытую позицию и тянет всё возможное. И да, что бы повысить точность определения когда роботу считать начало движения, я бы предложил брать последнюю свечу чьё тело закрылось выше хвостов предыдущих свечей. В таком случае, можно избежать тот процент холостых срабатываний, когда рынок находится в боковике. Поглядите сами на истории. Эта стратегия на Н1, будет работать на любом рынке. Единственно, что опасно в такой стратегии это торговля фьючерсами на всю котлету. А вот акциями самое оно. Лично от себя, могу предложить менее рисковую стратегию где тем же роботом, можно брать от двух и более сделок за торговую сессию с минимальным стопом и в случае разворота рынка против, забирать всё те же цифры, описанные в вашей стратегии.
avatar
Андрей &, продолжение следует.... 
avatar
Nekto Finkelmaer, продолжение последует если это кому то нужно будет, а так расписывать пару сотен букв в воздух — смысл? Ради интереса, погонял на истории вашу стратегию принципа 0,5% движения цены. Взял фьючерс рубля/доллар, юань/рубль и пару российских акций. За основу, часовой ТФ. Отсчёт в обратную сторону, брал от максимума текущего часа. Результат… пугающий. В хорошем смысле. Если брать на примере (сишки), то по стопу в те же 0,5% сносит раз в несколько месяцев. В остальное время, идёт набор прибыли. Можно организовать усреднение и снизить коэфф. убытка, но такое не по мне. Самое сложное это фиксация прибыли. Здесь нужно думать алгоритм загрузки/разгрузки со смещением стопа. Цена довольно часто, даёт весьма мощные движения, а иногда всего 100-200 пунктов. В общем, буду думать. Сейчас же на обкатку, поставил робота в боевое (дежурство) работать по этому принципу т.е. только на открытие позиции. (тащить) сделку будет другой робот, специально под это заточенный, но думаю, что в таком случае, алгоритм должен быть совершенно иной. Поглядим, что из всего этого выйдет в реале через пару месяцев. Но вообще, идея неплохая. Весьма. В дальнейшем, можно попробовать, загнать её на Форекс. Там где отсутствует реальное отображение графика объёма, подобная стратегия будет очень хороша. Ещё хороший вариант, торговать подобную стратегию на открытии рынка от максимума предыдущего дня. Зачастую, это даёт самые жирные куски. В общем, как вариант для тех кто не особо заморачивается кратковременной просадкой в несколько сот пунктов, а так же иногда потери 0,5% от суммы входа, стратегия вполне имеет право на существование.
avatar
Андрей &, сейчас уже можно сравнить доходности наших систем, мои результаты в следующей публикации.
avatar
Система протестирована и неплохо работает на высоколиквидных маловолатильных инструментах.
Можно ли увидеть результаты тестов?
И как вот из этого:
При движении цены в одном направлении на пол-процента вероятность движения еще на одну десятую составляет 80%
При этом вероятность возврата цены к открытию составляет 20%
можно сделать вывод: 
Направленное движение всегда продолжается.
Надо бы определить сначала и в цифрах изобразить, что значит направленное. Тогда и проверить что-то возможно станет.
avatar
svgr, конечно, вот только что опубликовал со скринами
avatar
И это, не видите ли косяка в построениях?
Для анализа также потребуется потенциальный размер дохода
— в случае зеленой свечи (Закрытие-Открытие)/Открытие
— в случае красной свечи (Открытие-Закрытие)/Открытие
На открытии Вы не знаете цвет начатой свечи, а используете его в вычислениях. )
avatar
svgr, использую статистику, за неимением дара видеть будущее🙂
avatar
svgr, давайте попробую объяснить.
У каждой свечи есть тень до открытия, у 80 процентов свечей эта тень меньше полпроцента движения цены, таким образом мы может предположить, что и последующих свечей тень не превысит полпроцента. В таком случае если цена прошла этот порог, то врятли развернется, поскольку первое предположение будет не верно

Простите, если опять не понятно, как смог… Мой талант преподавателя иссяк много лет назад. 🙂
avatar
Nekto Finkelmaer, по-прежнему имеются сомнения в верности рассуждений. 
1) Если минимум текущей свечи отклонился от её открытия более чем на 0,5%, то ничто не мешает в этой же свече переписать максимум так же более чем на 0,5% от открытия. Как-то это в статистике учитывается?
2) Не ясно в какой момент входить и в какую сторону. Преодоление минимального отклонения в 0,5% никак статистически не влияет на последующее поведение цены в оставшееся время свечи. Оно по-прежнему равновероятно в обе стороны. Легко проверяется тестами.
avatar
svgr,
1.Все верно, ничего не мешает, но случится это только для 20 свечей из ста (согласно статистике)
2.Опять все верно, но стоит учесть, что движение цены, в этом направлении, 70 свечей из 100 достигнет 0.7%. Не ясно только когда, и какие движение будут этому предшествовать.
avatar
Теперь более понятно. Составлял аналогичную статистику не для свечей, а для зигзага лет пять назад.
Какие выводы по представленному подходу? 
Вы должны выбрать период свечей, в котором статистика наиболее проявлена в нужном ключе. Для одного инструмента он более-менее стабилен.
Это всё слегка взлетит только для некоторых инструментов.
В общем случае устойчивого заработка нет. Мелкие выигрыши по 0,1-0,2% съест комиссия более чем наполовину. А добьют накопленный небольшой плюс те 20% случаев больших сливов, когда будут случаться походы к противоположным полюсам свечи.
avatar
svgr, не такие уж и мелкие, на графике можно увидеть, что 40 свечей из 100 делают 1.1% движения, а это уже 0.6% для базового актива и 4.8 для фьючерса, в годовых 120%
Выводы интересны тем, что при уменьшении вероятности получения прибыли она растет.
Наилучшие показатели были 0.54% вход, 5% тейк.
Феномен не изучен, поэтому удивляет. 🙂
avatar
Nekto Finkelmaer, когда повертите больше отрезков времени, инструментов, увидите, что дела обстоят так, как я описал. Например, ваши 0,54% и 5% в годах 2018 или 2015 перестанут быть лучшими. Может и убыток возникнуть.
Следующим шагом надо увидеть, что есть инструменты и ТФ, при которых входить надо вообще в другую сторону.
А общее замечание — в вашем подходе нужно использовать логарифмы цен. Сейчас у Вас % вверх ничем не ограничен, а вниз только 100%. Статистика перекошена.
avatar
svgr, я сторонник простых решений.
Использование сложных математических расчетов никак не влияет на движение цены. Движения случайны по определению, но есть какая то вероятность, что цена придет в нужную мне точку, весь расчет только на это.
avatar
Nekto Finkelmaer, последний пост в рамках помощи. Думаю, бесполезно.
Вероятности, на которые Вы уповаете, надо уметь считать. Или получить иным достоверным способом.
Сгенерируйте СБ. Это тоже нетривиальная задача — сгенерировать свечи, полученные по СБ. Постройте ваши линии на них. Характеристика линии входа при СБ — нулевое матожидание результата для каждой точки входа при нулевой комиссии.
Затем откладываете двойную комиссию от неё вверх и вниз для данной цены. Получите коридор, в котором выходы будут убыточными из-за комиссии. 
После чего можете строить линию выходов реального инструмента. Для входа в продолжение она должна быть выше коридора входов, для входа на возврат — ниже коридора. Расстояния от выходов до коридора и есть средний доход на одну сделку (вх+вых).
avatar

теги блога Nekto Finkelmaer

....все тэги



UPDONW
Новый дизайн