找回密码
 注册
搜索
查看: 2989|回复: 17

ninjatrader怎么对两个DataSeries进行运算?

[复制链接]
发表于 2017-5-31 06:57 PM | 显示全部楼层 |阅读模式


不好意思问个初级问题:譬如我有两个股票AAPL跟GOOGLE.
我的策略是:

Enter Long if
AAPL/GOOGLE < Bollinger Band (AAPL/GOOGLE, 20, 2) (低于BBand下沿)

Enter Short if
AAPL/GOOGLE > Bollinger Band (AAPL/GOOGLE, 20, 2)(高于BBand上沿)

其中AAPL跟GOOGLE是两个Data Series,Ninja里面好像不能直接用Data相除。
发表于 2017-5-31 08:26 PM | 显示全部楼层
自己编写一个自动交易程序,比通过ninjatrader制定交易规则,要方便容易的多。
回复 鲜花 鸡蛋

使用道具 举报

 楼主| 发表于 2017-5-31 08:47 PM | 显示全部楼层
盈透阿狗 发表于 2017-5-31 08:26 PM
自己编写一个自动交易程序,比通过ninjatrader制定交易规则,要方便容易的多。

多谢回答,请问您用什么平台写自动交易程序呢?
回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-5-31 09:29 PM | 显示全部楼层
本帖最后由 坚强的蛋炒饭 于 2017-5-31 09:31 PM 编辑

我记得STOCKCHARTS 好象可以 做除法比较的.
我多年不用了. 不知道现在是否还可以?
回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-5-31 10:16 PM | 显示全部楼层
你要先写一个两个dataseries相除的indicator,然后对这个indicator去bollinger.

dataseries相除的indicator我正好写了一个,你在这基础上加bollinger就可以了。以下是NJ7的代码。


#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
#endregion

// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
    /// <summary>
    /// Plot relative strength between two symbols.
    /// </summary>
    [Description("Plot relative strength between two symbols.")]
    public class RelativeStrength : Indicator
    {
        #region Variables
        // Wizard generated variables
            private string dividendSymbol = @""; // Default setting for DividendSymbol
            private string dividerSymbol = @""; // Default setting for DividerSymbol
        // User defined variables (add any user defined variables below)
                        private bool invertOnly = false ;
        #endregion

        /// <summary>
        /// This method is used to configure the indicator and is called once before any bar data is loaded.
        /// </summary>
        protected override void Initialize()
        {
                        if( String.Compare( this.dividendSymbol, "^ONE", true ) == 0 )
                                this.invertOnly = true ;
                        else if( this.dividendSymbol != "" )
                                //Add( this.dividendSymbol, this.BarsPeriod.Id, this.BarsPeriod.Value ) ;
                                Add( this.dividendSymbol, PeriodType.Day, 1 ) ;
                       
                        if( this.dividerSymbol != "" )
                                //Add( this.dividerSymbol, this.BarsPeriod.Id, this.BarsPeriod.Value ) ;
                                Add( this.dividerSymbol, PeriodType.Day, 1 ) ;
                               
            Add( new Plot( Color.Orange, "RelativeStrength" ) ) ;
                       
            Overlay                                = false ;
                        DisplayInDataBox        = false ;
                        PaintPriceMarkers        = false ;
                       
        }
               
        /// <summary>
        /// Called on each bar update event (incoming tick)
        /// </summary>
        protected override void OnBarUpdate()
        {
                        // We have multiple bars, so skip if this is not called for primay bar.
                        if( this.BarsInProgress != 0 )
                                return ;               
                       
                        Value.Set( 0 ) ;
                       
                        // No parameter specified, then simply invert the main data.
                        if( this.dividendSymbol == "" && this.dividerSymbol == "" ||
                                this.invertOnly && this.dividerSymbol == "" )
                        {
                                Value.Set( 1.0 / Close[0] ) ;
                                return ;
                        }
                       
                        if( this.dividendSymbol != "" && this.dividerSymbol != "" )
                        {
                                // No data for the first symbol yet.
                                if( this.CurrentBars[1] < 0 )
                                        return ;
                               
                                // No data for the 2nd symbol yet.
                                if( !this.invertOnly && this.CurrentBars[2] < 0 )
                                        return ;
                        }
                       
                        if( this.invertOnly )
                                Value.Set( 1.0 / Closes[1][0] ) ;
                        else
                    Value.Set( Closes[1][0] / Closes[2][0] ) ;
                       
        }

        #region Properties
        [Description("Dividend symbol. Use ^ONE to reverse the DividerSymobl.")]
        [GridCategory("Parameters")]
        public string DividendSymbol
        {
            get { return dividendSymbol; }
            set { dividendSymbol = value; }
        }

        [Description("Divider symbol.")]
        [GridCategory("Parameters")]
        public string DividerSymbol
        {
            get { return dividerSymbol; }
            set { dividerSymbol = value; }
        }
        #endregion
               
    }
       
}

#region NinjaScript generated code. Neither change nor remove.
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
    public partial class Indicator : IndicatorBase
    {
        private RelativeStrength[] cacheRelativeStrength = null;

        private static RelativeStrength checkRelativeStrength = new RelativeStrength();

        /// <summary>
        /// Plot relative strength between two symbols.
        /// </summary>
        /// <returns></returns>
        public RelativeStrength RelativeStrength(string dividendSymbol, string dividerSymbol)
        {
            return RelativeStrength(Input, dividendSymbol, dividerSymbol);
        }

        /// <summary>
        /// Plot relative strength between two symbols.
        /// </summary>
        /// <returns></returns>
        public RelativeStrength RelativeStrength(Data.IDataSeries input, string dividendSymbol, string dividerSymbol)
        {
            if (cacheRelativeStrength != null)
                for (int idx = 0; idx < cacheRelativeStrength.Length; idx++)
                    if (cacheRelativeStrength[idx].DividendSymbol == dividendSymbol && cacheRelativeStrength[idx].DividerSymbol == dividerSymbol && cacheRelativeStrength[idx].EqualsInput(input))
                        return cacheRelativeStrength[idx];

            lock (checkRelativeStrength)
            {
                checkRelativeStrength.DividendSymbol = dividendSymbol;
                dividendSymbol = checkRelativeStrength.DividendSymbol;
                checkRelativeStrength.DividerSymbol = dividerSymbol;
                dividerSymbol = checkRelativeStrength.DividerSymbol;

                if (cacheRelativeStrength != null)
                    for (int idx = 0; idx < cacheRelativeStrength.Length; idx++)
                        if (cacheRelativeStrength[idx].DividendSymbol == dividendSymbol && cacheRelativeStrength[idx].DividerSymbol == dividerSymbol && cacheRelativeStrength[idx].EqualsInput(input))
                            return cacheRelativeStrength[idx];

                RelativeStrength indicator = new RelativeStrength();
                indicator.BarsRequired = BarsRequired;
                indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
                indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
                indicator.MaximumBarsLookBack = MaximumBarsLookBack;
#endif
                indicator.Input = input;
                indicator.DividendSymbol = dividendSymbol;
                indicator.DividerSymbol = dividerSymbol;
                Indicators.Add(indicator);
                indicator.SetUp();

                RelativeStrength[] tmp = new RelativeStrength[cacheRelativeStrength == null ? 1 : cacheRelativeStrength.Length + 1];
                if (cacheRelativeStrength != null)
                    cacheRelativeStrength.CopyTo(tmp, 0);
                tmp[tmp.Length - 1] = indicator;
                cacheRelativeStrength = tmp;
                return indicator;
            }
        }
    }
}

// This namespace holds all market analyzer column definitions and is required. Do not change it.
namespace NinjaTrader.MarketAnalyzer
{
    public partial class Column : ColumnBase
    {
        /// <summary>
        /// Plot relative strength between two symbols.
        /// </summary>
        /// <returns></returns>
        [Gui.Design.WizardCondition("Indicator")]
        public Indicator.RelativeStrength RelativeStrength(string dividendSymbol, string dividerSymbol)
        {
            return _indicator.RelativeStrength(Input, dividendSymbol, dividerSymbol);
        }

        /// <summary>
        /// Plot relative strength between two symbols.
        /// </summary>
        /// <returns></returns>
        public Indicator.RelativeStrength RelativeStrength(Data.IDataSeries input, string dividendSymbol, string dividerSymbol)
        {
            return _indicator.RelativeStrength(input, dividendSymbol, dividerSymbol);
        }
    }
}

// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
    public partial class Strategy : StrategyBase
    {
        /// <summary>
        /// Plot relative strength between two symbols.
        /// </summary>
        /// <returns></returns>
        [Gui.Design.WizardCondition("Indicator")]
        public Indicator.RelativeStrength RelativeStrength(string dividendSymbol, string dividerSymbol)
        {
            return _indicator.RelativeStrength(Input, dividendSymbol, dividerSymbol);
        }

        /// <summary>
        /// Plot relative strength between two symbols.
        /// </summary>
        /// <returns></returns>
        public Indicator.RelativeStrength RelativeStrength(Data.IDataSeries input, string dividendSymbol, string dividerSymbol)
        {
            if (InInitialize && input == null)
                throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");

            return _indicator.RelativeStrength(input, dividendSymbol, dividerSymbol);
        }
    }
}
#endregion

点评

虽然与我无用, 但对班主的为人, 要点赞.  发表于 2017-6-1 10:23 AM

评分

1

查看全部评分

回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-5-31 10:22 PM | 显示全部楼层
^ONE的参数解释一下,可能有人只想对price取倒数,所以就引入了^ONE,否则就是两个symbol做参数就好,你的情况是AAPL和GOOGL,把我的代码直接拷贝入你新创建的indicator,就好了,记得要覆盖新创建的indicator自动生成的所有代码。

使用的时候就是这样的:



RelativeStrength( AAPL, GOOGL )[0] < Bollinger( RelativeStrength( AAPL, GOOGL ), 20, 2 ).Lower[0]

评分

1

查看全部评分

回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-5-31 10:24 PM | 显示全部楼层
再说一遍,这代码是for NT7的,你是NT8的话,不能直接用,要转换成NT8的格式,或者copy我代码中真正运算的部分到你NT8自动生成的indicator里。

评分

1

查看全部评分

回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-5-31 10:27 PM | 显示全部楼层
这个告诉你如何生成new indicator。你在wizard出来后,不用点击next,直接点击generate。然后把我的代码整个覆盖进去就好了。
1.png

评分

1

查看全部评分

回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-5-31 10:36 PM | 显示全部楼层
嗯,不用那么麻烦,我生成了一个dll,你直接就可以用了。好像copy到NT7/bin目录下就能用了,具体我忘了,你自己试试吧。源程序我也给你了,good luck。

RelativeStrength.zip

8.02 KB, 下载次数: 89

评分

1

查看全部评分

回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 03:32 AM | 显示全部楼层
Cobra 发表于 2017-5-31 10:22 PM
^ONE的参数解释一下,可能有人只想对price取倒数,所以就引入了^ONE,否则就是两个symbol做参数就好,你的情 ...

老蛇大雅才。听听京剧里是这么唱的。得把名字换一下。
https://www.youtube.com/watch?v=9IYo3hGD0KI

评分

1

查看全部评分

回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 03:32 AM | 显示全部楼层
1,求师,得到老蛇等专家指导。他们写Ninja Script十几年,老码农识途,或者说熟能生巧,巧而成精。
2,拜友,找个当地炒股码农,聊聊天, 谈笑间,樯橹灰飞烟灭。
3,自学。打开NijiaTrade,
先File-->connect-->External Date Feed,确保AAPL和GOOGLE的数据来源。
再Tools-->Edit NinjaScript -->Bollinger, 熟悉一下这个指标的源码结构。
然后Tools-->New Ninja Script,安部就班写吗。

不会写,或者写错误,一点也不丢人,就反复查Help-->Ninja Script,以及Tutorials,熟能生巧,巧而成精.


听说,Ninja的Build System,可把手机数据画图出来,没实践,期盼你和高手方便的时候指教。

评分

1

查看全部评分

回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 06:42 AM | 显示全部楼层
chuaner 发表于 2017-5-31 08:47 PM 多谢回答,请问您用什么平台写自动交易程序呢?
我使用的是Interactive Broker, 交易平台是: Trader Workstation (TWS), 支持Windows、Linux、包括手机等多平台。 支持多种编成语言接口,如Java,C++等:

我的自动交易系统是使用跨平台Qt C++完成的。分为数据采集、交易算法和自动交易三个模块。
  1. 数据采集,可以使用yahoo或Google提供免费接口,也可以自由改换到IB的商业接口:
        void reqMktData(TickerId id, const Contract &contract,const std::string &genericTicks, bool snapshot, const TagValueListSPtr& mktDataOptions);
  2. 交易算法是交易规则的集合,经过训练、学习、优化、卷积、回测得到的稳定系统。
  3. 自动交易就是把买卖信号提交给TWS的一个函数调用:
        void placeOrder(long id, const Contract &contract, const Order &order);
自己动手,丰衣足食。
回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 08:40 AM | 显示全部楼层
楼上的老大都很牛
回复 鲜花 鸡蛋

使用道具 举报

 楼主| 发表于 2017-6-1 08:45 PM | 显示全部楼层
Cobra 发表于 2017-5-31 10:16 PM
你要先写一个两个dataseries相除的indicator,然后对这个indicator去bollinger.

dataseries相除的indica ...

哇塞,太赞了,多谢老大,我回去研究一下。
回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 09:28 PM | 显示全部楼层
回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 09:59 PM | 显示全部楼层
盈透阿狗 发表于 2017-6-1 06:42 AM
我使用的是Interactive Broker,
交易平台是: Trader Workstation (TWS), 支持Windows、Linux、包括手机 ...

laoda,
can you share your 数据采集?
回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 10:15 PM | 显示全部楼层
回复 鲜花 鸡蛋

使用道具 举报

发表于 2017-6-1 10:19 PM | 显示全部楼层
littletiger 发表于 2017-6-1 09:59 PM laoda, can you share your 数据采集?

自动交易三部曲:

  • (1)先从采集数据开始;
  • (2)再总结经验,开发算法;
  • (3)再回测、优化。
做任何事情,都要有方法。如果你知道做某一件事情的方法。那么,你会觉得很好做,一点也不难。这就是【会者不难】。 同样,如果你不知道做某一件事情的最佳方法,那么,你会觉得很难做。这就是【难者不会】。

有些朋友可能会说“万事开头难”,那我就说说第一步:如何采集股票的交易价格。

把下面一行,拷贝到你的网页浏览器的地址中,按回车 就会得到SPY这支股票的当前价格。

得到的字串中包含“l”:最新交易的价格,以及“lt_dts”交易发生的时间:
"l":"238.38",	
"lt_dts":"2017-05-02T10:14:25Z"
如果写一个循环程序,每分钟询问一次,你就可以得到每分钟SPY的交易的实时价格时间序列。这就完成了第一步,数据采集,就这么简单。
回复 鲜花 鸡蛋

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|www.hutong9.net

GMT-5, 2024-11-28 11:47 AM , Processed in 0.115473 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表