2013年4月3日星期三

Add Trading Log on AmiBroker Chart(EOD)

将股票交易记录(交割单)的买卖信息画到Amibroker的chart中。

交易结果不佳的时候整理交易记录是个让人心烦的事情,3月份表现不好,干脆写了afl把所有交易记录都画到AB的chart上。

Step1. 用excel将通达信的交割单处理成txt文本文件,格式是“date,buy/sell,symbol,price,lots"。

TradeLog.txt sample(No title line):

2/28/2013,buy,000043,7.13,1000
3/1/2013,sell,000043,7.32,1000

Step2. 在AB中运行scan [Scan]ReadTradeLog.afl. 目的是读取txt文件信息,合并存储在静态变量中(code as followed).


/*  ---------------[Scan]ReadTradeLog.afl---------------------------------------
read trade log from TradeLog.txt and add buy@price text on the charts
  1. First, run scan using this afl to initialize static variables
  2. Then use TradeCheck layouts to check every operated stock chart(with indicator
TradeLogDrawing program    
                                        2013-3-23  ZYHuang                   */

Procedure getTradeLogInfo(sFileName)

/* get the trading log information and store in static variables
OpDate="20130303,20130403,20130202,...."
Op="buy,sell,buy,sell,buy,buy,"
Sbl="002234,002234,000043,000043,234543,234544,"
Prc="1.25,1.34,3.33,3.55,2.33,4.55,"
Lots="100,100,400,200,300,300," 
*/
OpDate=Op=Sbl=Prc=Lots="";
fh=fopen(sFileName,"r");
if(fh)
{
while(!feof(fh))
{
temp=fgets(fh);
OpDate=OpDate+strextract(temp,0)+",";
Op=Op+strextract(temp,1)+",";
Sbl=Sbl+strextract(temp,2)+",";
Prc=Prc+strExtract(temp,3)+",";
Lots=Lots+strLeft(strextract(temp,-1),strLen(strextract(temp,-1))-1)+","; //exclude the last Enter Code
}
fclose(fh);
}
staticVarSetTEXT("svOpDate",OpDate);
staticVarSetTEXT("svOp",Op);
staticVarSetTEXT("svSbl",Sbl);
staticVarSetTEXT("svPrc",Prc);
staticVarSetTEXT("svLots",Lots);
}

getTradeLogInfo("E:\\TradeLog.txt");
buy=0;  //for scan
  

Step3. 在AB中使用[I]DrawTradeLogOnChart.afl建立chart(code as followed).


/*       ----------------- [I]DrawTradeLogOnChart.afl  ---------------------------
read static variables to draw trading operation on the chart
TradeLogDrawing program    
                                        2013-3-23  ZYHuang                   */

//------Initial low-level graphic infomation and funcions -------begin----
lvb=status("lastvisiblebar");
fvb=status("firstvisiblebar");
chartwidth=status("pxchartwidth");
chartleft=status("pxchartleft");
barwidth=chartwidth/(lvb-fvb+1);

function GetVisibleBarCount()        
{
return min(lvb-fvb,barcount-fvb); //lastvisiblebar could include the "blank" bar at chart right
}                                     

function GfxConvertBarToPixelx(bar)  //bar is zero based visible barcount
{
return chartleft+bar*barwidth;
}

function GfxConvertValueToPixelY(value)
{
local miny,maxy,chartbottom,chartheight;
miny=status("axisminy");
maxy=status("axismaxy");
chartbottom=status("pxchartbottom");
chartheight=status("pxchartheight");
return chartbottom-floor(0.5+(value-miny)*chartheight/(maxy-miny));
}
//----------Initial low-level graphic infomation and funcions --------------end-----

Procedure subDrawLog(num)
{
oPdate=strtodatetime(strExtract(staticVarGetText("svOpDate"),num));
oP=strextract(staticvargettext("svOp"),num);
oPpc=strToNum(strextract(staticvargettext("svPrc"),num));
oPlt=strextract(staticvargettext("svLots"),num);
txtcolor=colorgreen;
if (oP=="buy") txtcolor=colorred;
GfxSetOverLayMode(0);
barNum=GetVisibleBarCount();
GfxSelectFont( "Tahoma",7,500,false,true);
Gfxsettextcolor(txtcolor);
ObjectDateBarcount=lookup(barindex(),oPdate,0);

if (!isnull(ObjectDateBarcount) )
{   //Draw 

left=GfxConvertBarToPixelx(objectdatebarcount-fvb)+barwidth/3;
bottom=GfxConvertValueToPixely(Oppc);
right=left+15*barwidth;
top=bottom-20;
txt=strformat(strtoupper(strleft(oP,1)))+oPlt+"@"+oPpc;
GfxDrawText(txt,left,top,right,bottom,32+8);
}
}  //sub end

//Main 
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
requesttimedrefresh(1);
stocklist=staticVarGetText("svSbl");
plot(c,"price",colorblack,stylecandle);

GfxSelectFont( "Tahoma",11.5,700,false,true);
GfxSetBKcolor(coloryellow);
Gfxsettextcolor(colorblue);
gfxtextout("Do scan first",865,620);
for (i=0; i<strCount(stocklist,",");i++)
{
if (strleft(name(),6)==strExtract(stocklist,i))
{
subDrawLog(i);
}
}

2013年4月2日星期二

Seasonality System Upgrade

    用RSI构建了一个交易系统,无论怎么修改都是个赔钱机器,只好放弃。不过过程中想到的一个选股策略好像不错,放到F#1系统中效果很好。原来的F#1每次交易的股票数量越多,资金曲线越平滑,而受限人工下单方式,实际操作效果不好。而且系统进入2012年第四季后(即实测后)表现退化,基本没有投入资金使用过。
    修改了选股策略后,最优的股票数量是双峰(4只和20只),对不同板块测试,周期性的板块结果明显优于非周期性板块,这也符合逻辑。本质上这个系统的获利来自对波动性的追逐。最重要的是,样本外数据的测试结果没有退化,可以进入实战检验看看了。

In-sample data period(Optimize):  2008.1.1-2011.12.31
Out of smaple data period(Check): 2004.1.1-2013.4.1
Statistics
All trades Long trades
Initial capital 109994 109994
Ending capital 1230175.97 1230175.97
Net Profit 1120181.97 1120181.97
Net Profit % 1018.40% 1018.40%
Exposure % 9.49% 9.49%
Net Risk Adjusted Return % 10732.79% 10732.79%
Annual Return % 29.81% 29.81%
Risk Adjusted Return % 314.15% 314.15%
All trades 803 803 (100.00 %)
 Avg. Profit/Loss 1395 1395
 Avg. Profit/Loss % 1.26% 1.26%
 Avg. Bars Held 2.08 2.08
Winners 537 (66.87 %) 537 (66.87 %)
 Total Profit 1702620.88 1702620.88
 Avg. Profit 3170.62 3170.62
 Avg. Profit % 2.85% 2.85%
 Avg. Bars Held 2.09 2.09
 Max. Consecutive 19 19
 Largest win 26623.74 26623.74
 # bars in largest win 4 4
Losers 266 (33.13 %) 266 (33.13 %)
 Total Loss -582438.91 -582438.91
 Avg. Loss -2189.62 -2189.62
 Avg. Loss % -1.96% -1.96%
 Avg. Bars Held 2.07 2.07
 Max. Consecutive 8 8
 Largest loss -15706.06 -15706.06
 # bars in largest loss 2 2
Max. trade drawdown -15706.06 -15706.06
Max. trade % drawdown -10.09% -10.09%
Max. system drawdown -57512.68 -57512.68
Max. system % drawdown -6.17% -6.17%
Recovery Factor 19.48 19.48
CAR/MaxDD 4.83 4.83
RAR/MaxDD 50.92 50.92
Profit Factor 2.92 2.92
Payoff Ratio 1.45 1.45
Standard Error 100127.66 100127.66
Risk-Reward Ratio 1.29 1.29
Ulcer Index 1.44 1.44
Ulcer Performance Index 16.91 16.91
Sharpe Ratio of trades 3.67 3.67
K-Ratio 0.0727 0.0727






2013年1月28日星期一

2013国内股票市场周期预测(market timing)

根据经济周期(使用CPI衡量)得到最好和最差两种情形,基本上对应的是主流观点的去库存还是去产能。市场将在4,5月份给出答案。